/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/screener/Screener.Criteria.js
*/

var ScreenerCriteria = function() {};

ScreenerCriteria.prototype.CODE_DEFAULT = "ALL";
ScreenerCriteria.prototype.CODE_ALL = "ALL";
ScreenerCriteria.prototype.CODE_POPULAR = "POP";

ScreenerCriteria.prototype.CLASS_EUROPE_MAP = "europe";
ScreenerCriteria.prototype.CLASS_ASIA_MAP = "asia";
ScreenerCriteria.prototype.CLASS_TEXT_ONLY = "textDisplay";

ScreenerCriteria.prototype.PRIMARY_CRITERIA = {
	"CountryCode": true,
	"IndustryCode": true,
	"IndustryName": true
}

ScreenerCriteria.prototype.MAP_COORDINATES = {
	"ZA":{x: 156, y: 123},
	"AR":{x: 87, y: 128},
	"BR":{x: 95, y: 106},
	"CA":{x: 57, y: 47},
	"CL":{x: 77, y: 127},
	"MX":{x: 50, y: 74},
	"US":{x: 70, y: 54, xPopular: 70, yPopular: 54},
	"AU":{x: 251, y: 116},
	"CN":{x: 149, y: 70, xPopular: 241, yPopular: 64},
	"HK":{x: 135, y: 86},
	"ID":{x: 143, y: 148},
	"IN":{x: 56, y: 84},
	"JP":{x: 187, y: 48, xPopular: 261, yPopular: 54},
	"KR":{x: 160, y: 52},
	"MY":{x: 113, y: 132},
	"NZ":{x: 274, y: 126},
	"SG":{x: 120, y: 143},
	"TH":{x: 111, y: 110},
	"TW":{x: 156, y: 84},
	"BE":{x: 95, y: 58},
	"CH":{x: 114, y: 81},
	"CZ":{x: 144, y: 62},
	"DE":{x: 129, y: 54},
	"DK":{x: 122, y: 25},
	"EE":{x: 191, y: 8},
	"ES":{x: 53, y: 123},
	"FI":{x: 183, y: 1},
	"FR":{x: 82, y: 73},
	"GB":{x: 82, y: 50, xPopular: 134, yPopular: 34},
	"GR":{x: 191, y: 134},
	"HU":{x: 168, y: 79},
	"IE":{x: 45, y: 43},
	"IS":{x: 33, y: 1},
	"IT":{x: 144, y: 114},
	"LT":{x: 188, y: 33},
	"NL":{x: 100, y: 47},
	"NO":{x: 120, y: 8},
	"PL":{x: 171, y: 53},
	"PT":{x: 30, y: 125},
	"RO":{x: 203, y: 93},
	"RU":{x: 226, y: 2},
	"SE":{x: 157, y: 8},
	"SI":{x: 144, y: 87},
	"TR":{x: 233, y: 130}
}

ScreenerCriteria.prototype.init = function() {
	var regionControls = Element.parseSelector("div.regionalFocus ul li a", "wsod");
	var sectorsAndIndustries = Element.parseSelector("div.sectorsAndIndustries ul li a", "wsod");
	var viewMatches = Element.getParentBySelector("totalMatches", "div.basicButton");
	var addAdditionalCriteria = Element.get('addAdditionalCriteria') || false;
	
	
	var countries = this.getCountries();
	var industries = this.getIndustries();

	var activeCodeRegion = this.CODE_DEFAULT;
	if (countries.getParentObject()[this.CODE_POPULAR]) {
		activeCodeRegion = this.CODE_POPULAR;
	} else {
		for (var i in countries.getParentObject()) {
			activeCodeRegion = i;
			break;
		}
	}
	
	var activeCodeSector = this.CODE_DEFAULT;
	if (industries.getParentObject()[this.CODE_POPULAR]) {
		activeCodeSector = this.CODE_POPULAR;
	} else {
		for (var i in industries.getParentObject()) {
			activeCodeSector = i;
			break;
		}
	}
	
	var toggleRegion = this.getEventManager().add(null, "click", this.toggleRegion, this);
	for (var i = 0, regionCode; i < regionControls.length; i++) {
		regionCode = regionControls[i].getAttribute("regionCode");
		
		toggleRegion.addElement(regionControls[i]);
		if (activeCodeRegion == regionCode) { this.toggleRegion(null, regionControls[i]); }
	}
	
 	var toggleSector = this.getEventManager().add(null, "click", this.toggleSector, this);
	for (var i = 0, sectorCode; i < sectorsAndIndustries.length; i++) {
		sectorCode = sectorsAndIndustries[i].getAttribute("sectorCode");
		
		toggleSector.addElement(sectorsAndIndustries[i]);
		if (activeCodeSector == sectorCode) { this.toggleSector(null, sectorsAndIndustries[i]); }
	}
	
	this.getEventManager().add(viewMatches, "click", this.viewMatches, this);
	
	this.getPreScreen(true);

	var criteriaPopup = this.getCriteriaPopup();
		criteriaPopup.setCriteria(this.getCriteria());
		criteriaPopup.SCREENER_CRITERIA = this.SCREENER_CRITERIA;

	if (addAdditionalCriteria) {
		this.getEventManager().add(
			{
				 context:	criteriaPopup
				,element:	addAdditionalCriteria
				,handler:	criteriaPopup.showThePopup
				,type:		'click'
			}
		);
	}
	
	this.initSaveCriteria();

	
	var currencies = Element.parseSelector("a[currency]","div-normalize-currency");
	this.getEventManager().add({
		context:	this,
		element:	currencies,
		handler:	function(e, el) {
			e.cancel();
			
			Element.removeClass(currencies,"selected");
			Element.addClass(el,"selected");
			var rate = el.getAttribute("rate");
			
			SecondaryCriteria.conversionRate = function() { return rate; }
			
			var criteria = this.getSecondaryCriteria();
			for(var i in criteria) {
				criteria[i].convertSliderData()
			}
		},
		type:		'click'
	})

	this.isInitialized(true);
}

ScreenerCriteria.prototype.initSaveCriteria = function(criteria) {
	var saveCriteria = Element.get('saveCriteria') || false;
	
	this.input_criteria = null;
	if(criteria) {
		this.input_criteria = this.getSerializer().deserialize(criteria);
	}
	if (saveCriteria) {
		this.getEventManager().add(
			{
				 context:	this
				,element:	saveCriteria
				,handler:	this.showTheSaveCriteriaPopup
				,type:		'click'
			}
		);
	}
}

ScreenerCriteria.prototype.initializeCurrency = function() {
	
	
	var defaultCurrency = Element.parseSelector("a[currency='GBP']","div-normalize-currency","first");
	Element.addClass(defaultCurrency,"selected")
	var rate = defaultCurrency.getAttribute("rate");
	SecondaryCriteria.conversionRate = function() { return rate; }
	
	this.initializeCurrency = function(){}
}

ScreenerCriteria.prototype.isInitialized = function(isInit) {
	var isInitialized = isInit || false;
	
	this.isInitialized = function(isInit) {
		isInitialized = isInit || isInitialized;
		
		return isInitialized;
	}
}

/**
 * @method showTheSaveCriteriaPopup
 */
ScreenerCriteria.prototype.showTheSaveCriteriaPopup = function(e, el) {
	var name = el.getAttribute("savedName") || "";
	var saveCriteriaPopup = this.getSaveCriteriaPopup(name);
		var criteria = this.input_criteria;
		if(!criteria) {
			criteria = this.getCriteria();
		}
		saveCriteriaPopup.setCriteria(criteria);
		saveCriteriaPopup.showThePopup();
}

ScreenerCriteria.prototype.getCriteriaOrder = function() {
	var counter = 0;
	var order = {};
	for(var i in this.SCREENER_CRITERIA) {
		order[i] = counter;
		counter++;
	}
	
	return (this.getCriteriaOrder = function() {
		return order;
	})();
}


ScreenerCriteria.prototype.getCriteria = function() {
	var countries = this.getCountries();
	var industries = this.getIndustries();

	var criteria = [];
		criteria.push(countries.exportCriteria());
		criteria.push(industries.exportCriteria());

	var secondaryCriteria = this.getSecondaryCriteria();
	
	var secondary = [];
	for (var i in secondaryCriteria) {
		secondary.push(this.getSecondaryCriteria(secondaryCriteria[i])[i].exportCriteria());
	}
	
	var order = this.getCriteriaOrder();
	secondary.sort(function(a,b) {
		return order[a.field] - order[b.field];
	});
	
	
	criteria = criteria.concat(secondary);
	return criteria;
}


ScreenerCriteria.prototype.setCriteria = function(criteria) {
	var criteria	= criteria || [];
	
	for (var i = 0, field; i < criteria.length; i++) {
		field = criteria[i].field;
		
		if (this.PRIMARY_CRITERIA[field]) {
			this.getPrimaryCriteria(criteria[i]);
		} else {
			this.getSecondaryCriteria(criteria[i])[field].exportCriteria();
		}
	}
}


/**
 * @method getCriteriaPopup
 *
 */
ScreenerCriteria.prototype.getCriteriaPopup = function() {
	var criteriaPopup = new CriteriaPopup(this);

	this.getCriteriaPopup = function() {
		return criteriaPopup;
	}

	return this.getCriteriaPopup();
}


/**
 * @method getSaveCriteriaPopup
 *
 */
ScreenerCriteria.prototype.getSaveCriteriaPopup = function(name) {
	var saveCriteriaPopup = new SaveCriteriaPopup(name);

	this.getSaveCriteriaPopup = function() {
		return saveCriteriaPopup;
	}

	return this.getSaveCriteriaPopup();
}


ScreenerCriteria.prototype.toggleRegion = function(e, el, data) {
	if (e) { e.cancel(); }
	el.blur();
	
	var regionCode = el.getAttribute("regionCode");
	var region = this.SCREENER_REGIONS[regionCode];
	var countries = this.getCountries();
	var countriesChildObj = countries.getChildObject();
	
	var elOptions = this.getRegionSubOptions();
	var elPanel = this.getRegionPanel();
	var elIcons = Element.parseSelector("div.icons", elPanel, "first");
	
	Element.removeClass(Element.parseSelector("ul li", elPanel), "active");
	Element.removeChildNodes(elOptions);
	Element.removeChildNodes(elIcons);
	Element.addClass(Element.getParent(el, "li"), "active");
	
	Element.removeClass(elPanel, this.CLASS_EUROPE_MAP);
	Element.removeClass(elPanel, this.CLASS_ASIA_MAP);
	Element.addClass(elPanel, region.map);
	
	if (region.text) {
		Element.addChild(elOptions,
			Element.create("div", {"class":this.CLASS_TEXT_ONLY}, region.text)
		);
		
		if (!countries.isAllView() && this.isInitialized()) { 
			countries.isAllView(true);
			this.getPreScreen(); 
		}
	} else {
		
		
		var all_entry;
		var ul = Element.create("ul", {}, [
			all_entry = Element.create("li", {}, [
				Element.create("input", {"type":"checkbox", value:this.CODE_ALL, "Events": [
					{type: "click", context: this, handler: this.countrySelect}
				]}),
				Element.create("span", {}, "All "+region.name),
				Element.create("br", {"class":"clear"})
			]),
			Element.create("br", {"class":"clear"})
		], elOptions);
		
		var icon, checkbox, coords;
		
		var numCountries = 0;
		for (var i in this.SCREENER_COUNTRIES) {
			if (this.SCREENER_COUNTRIES[i].regionCode == region.code || (this.CODE_POPULAR == region.code && this.SCREENER_COUNTRIES[i].isPopular)) {
				coords = this.MAP_COORDINATES[this.SCREENER_COUNTRIES[i].code] || {};
				
				if (coords.x && coords.y) {
					icon = Element.create("a", {
						"href":"javascript:void(0)", 
						"countryCode":this.SCREENER_COUNTRIES[i].code, 
						"class":"mapicon", 
						"name" : this.SCREENER_COUNTRIES[i].name,
						"Events": [
							{type: "click", context: this, handler: this.countrySelect}
						]
					}, [
						"&nbsp;",
						this._createNamePopup(this.SCREENER_COUNTRIES[i].name)
					], elIcons);
					
					if (this.CODE_POPULAR == region.code) { 
						Element.setXY(icon, coords.xPopular, coords.yPopular); 
					} else { 
						Element.setXY(icon, coords.x, coords.y); 
					}
				}
				
				Element.create("li", {}, [
					checkbox = Element.create("input", {"type":"checkbox", "value":this.SCREENER_COUNTRIES[i].code, "Events":
						{type: "click", context: this, handler: this.countrySelect}
					}),
					Element.create("span", {}, this.SCREENER_COUNTRIES[i].name),
					Element.create("br", {"class":"clear"})
				], ul);
				
				numCountries++;
				
				Element.create("br", {"class":"clear"}, null, ul);
				
				if (countriesChildObj[this.SCREENER_COUNTRIES[i].code]) {
					checkbox.checked = true;
					Element.addClass(icon, "active");
				}
			}
		}
		
		if(numCountries < 2) {
			Element.remove(all_entry)
		}
		
		if (countries.isAllView() && this.isInitialized()) { 
			countries.isAllView(false);
			this.getPreScreen(); 
		}
	}
	
	countries.renderActiveParents();
};

ScreenerCriteria.prototype._createNamePopup = function( name ) {
	var img;
	var el = Element.create("div",{ className:'country-hover-popup', id:'name-popup-'+name.toLowerCase().replace(/\s/g,"") },[
		Element.create("div",{className:'container'},
			Element.create("div",{className:'country-name'},String(name).replace(/\s/g, "&nbsp;"))
		)
	]);
	
	return el;
}

ScreenerCriteria.prototype.countrySelect = function(e, el, data) {
	var countries = this.getCountries();

	var isLink = "A" == el.tagName;

	if (isLink) {
		e.cancel();
		el.blur();
	}
	
	if (!el.checked || Element.hasClass(el, "active")) {
		Element.parseSelector("input[value='"+this.CODE_ALL+"']", this.getRegionSubOptions(), "first").checked = false;
	}
	
	var countryCode = isLink ? el.getAttribute("countryCode") : el.value;
	var country = this.SCREENER_COUNTRIES[countryCode];
	
	if (this.CODE_ALL == countryCode) {
		var countryCheckBoxes = Element.parseSelector("input[type='checkbox']", this.getRegionSubOptions());
		var countryBubbles = Element.parseSelector("a.mapicon", this.getRegionPanel());
		
		for (var i = 0; i < countryCheckBoxes.length; i++) {
			countryCheckBoxes[i].checked = el.checked ? true : false
		}
		
		if (el.checked) {
			Element.addClass(countryBubbles, "active");
			for (var i = 0; i < countryCheckBoxes.length; i++) {
				if (this.CODE_ALL != countryCheckBoxes[i].value) { countries.addChild(countryCheckBoxes[i].value);}
			}
		} else {
			Element.removeClass(countryBubbles, "active");
			for (var i = 0; i < countryCheckBoxes.length; i++) {
				if (this.CODE_ALL != countryCheckBoxes[i].value) { countries.removeChild(countryCheckBoxes[i].value);}
			}
		}
	} else {
		var countryBubble =  isLink ? el : Element.parseSelector("a[countryCode='" + country.code + "']", this.getRegionPanel(), "first");
		var countryCheckBox = isLink ? Element.parseSelector("input[value='" + country.code + "']", this.getRegionSubOptions(), "first") : el;	
		
		if (countryBubble) { Element.toggleClass(countryBubble, "active"); }
		if (isLink) { countryCheckBox.checked = !countryCheckBox.checked; }
		
		countries.toggleChild(country.code);
	}
	
	this.getPreScreen();
}

ScreenerCriteria.prototype.toggleSector = function(e, el, data) {
	if (e) { e.cancel(); }
	el.blur();
	
	var sectorCode = el.getAttribute("sectorCode");
	var sector = this.SCREENER_SECTORS[sectorCode];
	var industries = this.getIndustries();
	var industriesChildObj = industries.getChildObject();
	
	var elOptions = this.getSectorSubOptions();
	var elPanel = this.getSectorPanel();

	Element.removeClass(Element.parseSelector("ul li", elPanel), "active");
	Element.removeChildNodes(elOptions);
	Element.addClass(Element.getParent(el, "li"), "active");
	
	if (sector.text) {
		Element.addChild(elOptions,
			Element.create("div", {"class":this.CLASS_TEXT_ONLY}, sector.text)
		);
		
		if (!industries.isAllView() && this.isInitialized()) { 
			industries.isAllView(true);
			this.getPreScreen();
		}
	} else {
		
		var all_entry;
		var ul = Element.create("ul", {}, [
			all_entry = Element.create("li", {}, [
				Element.create("input", {"type":"checkbox", value:this.CODE_ALL, "Events": [
					{type: "click", context: this, handler: this.industrySelect}
				]}),
				Element.create("span", {}, "All "+sector.name),
				Element.create("br", {"class":"clear"})
			]),
			Element.create("br", {"class":"clear"})
		], elOptions);
		
		var numSectors = 0;
		var checkbox;
		for (var i in this.SCREENER_INDUSTRIES) {
			if (this.SCREENER_INDUSTRIES[i].sectorCode == sector.code || (this.CODE_POPULAR == sector.code && this.SCREENER_INDUSTRIES[i].isPopular)) {
				Element.create("li", {}, [
					checkbox = Element.create("input", {"type":"checkbox", "value":this.SCREENER_INDUSTRIES[i].code, "Events":
						{type: "click", context: this, handler: this.industrySelect}
					}),
					Element.create("span", {}, this.SCREENER_INDUSTRIES[i].name),
					Element.create("br", {"class":"clear"})
				], ul);
				numSectors++;
				
				Element.create("br", {"class":"clear"}, null, ul)
				
	 			if (industriesChildObj[this.SCREENER_INDUSTRIES[i].code]) {
					checkbox.checked = true;
				}
			}
		}
		
		if(numSectors < 2) {
			Element.remove(all_entry);
		}
		
		if (industries.isAllView() && this.isInitialized()) { 
			industries.isAllView(false);
			this.getPreScreen(); 
		}
	}
	
	industries.renderActiveParents();
};

ScreenerCriteria.prototype.industrySelect = function(e, el, data) {
	var industries = this.getIndustries();

	if (!el.checked) {
		Element.parseSelector("input[value='"+this.CODE_ALL+"']", this.getSectorSubOptions(), "first").checked = false;
	}
	
	var industryCode = el.value;
	var industry = this.SCREENER_INDUSTRIES[industryCode];
	
	if (this.CODE_ALL == industryCode) {
		var industryCheckBoxes = Element.parseSelector("input[type='checkbox']", this.getSectorSubOptions());
		
		for (var i = 0; i < industryCheckBoxes.length; i++) {
			industryCheckBoxes[i].checked = el.checked ? true : false
		}

		for (var i = 0; i < industryCheckBoxes.length; i++) {
			if (this.CODE_ALL != industryCheckBoxes[i].value && el.checked) { 
				industries.addChild(industryCheckBoxes[i].value);
			} else {
				industries.removeChild(industryCheckBoxes[i].value);
			}
		}
	} else {
		industries.toggleChild(industry.code);
	}

	this.getPreScreen();
}

ScreenerCriteria.prototype.getRegionPanel = function(e, el, data) {
	var elRegion = Element.parseSelector("div.regionalFocus div.panel", "wsod", "first");
	
	this.getRegionPanel = function() {
		return elRegion;
	};
	
	return this.getRegionPanel();
};

ScreenerCriteria.prototype.getRegionSubOptions = function(e, el, data) {
	var elRegionSubOptions = Element.parseSelector("div.regionalFocus div.suboptions", "wsod", "first");
	
	this.getRegionSubOptions = function() {
		return elRegionSubOptions;
	};
	
	return this.getRegionSubOptions();
};

ScreenerCriteria.prototype.getSectorPanel = function(e, el, data) {
	var elSector = Element.parseSelector("div.sectorsAndIndustries div.panel", "wsod", "first");
	
	this.getSectorPanel = function() {
		return elSector;
	};
	
	return this.getSectorPanel();
};


ScreenerCriteria.prototype.getSectorSubOptions = function(e, el, data) {
	var elSectorSubOptions = Element.parseSelector("div.sectorsAndIndustries div.suboptions", "wsod", "first");
	
	this.getSectorSubOptions = function() {
		return elSectorSubOptions;
	};
	
	return this.getSectorSubOptions();
};

ScreenerCriteria.prototype.getEventManager = function() {
	var em = new EventManager();
	this.getEventManager = function() {
		return em;
	};
	return this.getEventManager();
};

ScreenerCriteria.prototype.getCountries = function(field, values) {
	var countries = new PrimaryCriteria(field, values);
	countries.setCriteriaObject(this.SCREENER_COUNTRIES);
	for (var i = 0, values = countries.getValues(); i < values.length; i++) {
		countries.addChild(values[i]);
	}
	
	this.getCountries = function() {
		return countries;
	}
	
	return this.getCountries();
}

ScreenerCriteria.prototype.getIndustries = function(field, values) {
	var industries = new PrimaryCriteria(field, values);
	industries.setCriteriaObject(this.SCREENER_INDUSTRIES);
	
	for (var i = 0, values = industries.getValues(); i < values.length; i++) {
		industries.addChild(values[i]);
	}
	
	this.getIndustries = function() {
		return industries;
	}
	
	return this.getIndustries();
}

ScreenerCriteria.prototype.getPrimaryCriteria = function(criteria) {
	if ("CountryCode" == criteria.field) {
		this.getCountries(criteria.field, criteria.values);
	} else if ("IndustryCode" == criteria.field) {
		this.getIndustries(criteria.field, criteria.values);
	}
}

ScreenerCriteria.prototype.getSecondaryCriteria = function(criteria) {
	var secondaryCriteria = {};

	this.getSecondaryCriteria = function(criteria) {
		if (criteria && criteria.field && !secondaryCriteria[criteria.field]) {
			secondaryCriteria[criteria.field] = new SecondaryCriteria(this, criteria.field, criteria.values);
			secondaryCriteria[criteria.field].draw();
		}
//		console.log(secondaryCriteria);
		return secondaryCriteria;
	}
	
	return this.getSecondaryCriteria(criteria);
}


ScreenerCriteria.prototype.removeSecondaryCriteria = function(field) {
	var secondaryCriteria = this.getSecondaryCriteria()[field];
	
	if (secondaryCriteria) {
		delete this.getSecondaryCriteria()[field];
		
		this.getCriteriaPopup().setCriteria(this.getCriteria(), field);
		
		secondaryCriteria.getEventManager().removeAll();
		
		Element.remove(secondaryCriteria.getContent());
		
		this.getPreScreen();
	}
}

ScreenerCriteria.prototype.getCurrency = function() {
	var currency = Element.parseSelector("a[currency].selected","div-normalize-currency","first")
	if(!currency) { return null; }
	
	return(this.getCurrency = function() {
		return currency;
	})();
}

ScreenerCriteria.prototype.drawLoadingGraphic = function() {
	var screenerBox = Element.get("screenerCriteria");
	if(!screenerBox) { return; }
	
	if(!screenerBox.loadingOverlay) {
		var loadingGraphic;
		var overlay = Element.create("div",{className:'screener-loading wsodHidden'},
			loadingGraphic = Element.create("div",{className:'loading-graphic'},[
				Element.create("img",{src:"/ft/resources/image/loading.gif"}),
				Element.create("div",{className:"loading-text"},"Loading...")
			])
		,screenerBox);
		
		screenerBox.loadingOverlay = overlay;
		screenerBox.loadingOverlay.loadingGraphic = loadingGraphic;
	}
	
	var elSize = Element.getSize(screenerBox);
	Element.removeClass(screenerBox.loadingOverlay,"wsodHidden");
	Element.setSize(screenerBox.loadingOverlay,elSize.width, elSize.height);
	var loaderSize = Element.getSize(screenerBox.loadingOverlay.loadingGraphic);
	Element.setXY(screenerBox.loadingOverlay.loadingGraphic,(elSize.width/2)-(loaderSize.width/2),(elSize.height/2)-(loaderSize.height/2));
}

ScreenerCriteria.prototype.hideLoadingGraphic = function() {
	var screenerBox = Element.get("screenerCriteria");
	if(!screenerBox || !screenerBox.loadingOverlay) { return; }
	
	Element.addClass(screenerBox.loadingOverlay,"wsodHidden");
}

ScreenerCriteria.prototype.getPreScreen = function(criteriaChange) {
	var criteria = this.getCriteria();
	
	if(criteriaChange) { this.drawLoadingGraphic(); }
	
	var currency = this.getCurrency();
	
	this.getContentBuffer().abortRequests();
 	this.getContentBuffer().load({
		url: "/ft/resources/buffer/getScreenerCriteriaModule.asp",
		method: "post",
		contentType: "text/javascript",
		data: {
			criteria: this.getSerializer().serialize(criteria),
			currency: currency ? currency.getAttribute("currency") : "USD"
		},
		preventEval: true,
		debug: true,
		onload: function(cb) {

			this.initializeCurrency();
			
			var result = this.getSerializer().deserialize(cb.getResult());
			var secondaryCriteria = this.getSecondaryCriteria();
			
			var elMatches, elCumulativeMatches, matches, cumulativeMatches;
			for (var i in result) {
				elCumulativeMatches = Element.get(i+"CumulativeMatches");
				elMatches = Element.get(i+"Matches");
				matches = result[i].Matches;
				cumulativeMatches = result[i].CumulativeMatches;
				
				if (secondaryCriteria[i] && secondaryCriteria[i].isSliderItem()) {
					secondaryCriteria[i].setSliderValues(result[i]);
					secondaryCriteria[i].convertSliderData();
				}
				Element.setHTML(elCumulativeMatches, cumulativeMatches);
				Element.setHTML(elMatches, matches);
			}
			
			Element.setHTML("totalMatches", cumulativeMatches);
			
			if(criteriaChange) { this.hideLoadingGraphic(); }
			
		},
		context: this
	});
}

ScreenerCriteria.prototype.viewMatches = function() {
	var currency = Element.parseSelector("a[currency].selected","div-normalize-currency","first")
	currency = currency ? currency.getAttribute("currency") : "GBP"
	
	var elForm = Element.create("form", {"name":"viewMatches", "method":"post", "action":"screenerResults.asp"}, [
		Element.create("input", { "name":"criteria", "type":"hidden", "value":this.getSerializer().serialize(this.getCriteria()) }),
		Element.create("input", { "name":"currency", "type":"hidden", "value": currency})
	], document.body);
	
	elForm.submit();
}

ScreenerCriteria.prototype.getSerializer = function() {
	var s = new Serializer();
	
	this.getSerializer = function() {
		return s;
	}
	
	return this.getSerializer();
}

ScreenerCriteria.prototype.getContentBuffer = function() {
	var cb = new ContentBuffer()
	
	this.getContentBuffer = function() {
		return cb;
	}
	
	return this.getContentBuffer();
}



function ScreenerNews(oArgs) { 
	//this.wsodissue = wsodissue;
	
	for(var i in oArgs) {
		this[i] = oArgs[i];
	}
	
	this.init(); 
}

ScreenerNews.containers = [];

ScreenerNews.prototype.getContentBuffer = function() {
	var cb = new ContentBuffer()
	
	this.getContentBuffer = function() {
		return cb;
	}
	
	return this.getContentBuffer();
}
ScreenerNews.prototype.getSerializer = function() {
	var s = new Serializer();
	
	this.getSerializer = function() {
		return s;
	}
	
	return this.getSerializer();
}
ScreenerNews.prototype.init = function() {
	this.getContentBuffer().abortRequests();
 	this.getContentBuffer().load({
		url: "/ft/resources/buffer/getScreenerNews.asp",
		method: "post",
		contentType: "text/javascript",
		data: {
			wsodissue: this.wsodissue
		},
		preventEval: true,
		debug: true,
		onload: function(cb) {
			var result = this.getSerializer().deserialize(cb.getResult());
			this.draw(this.e, this.el, result);
		},
		context: this
	});
}

ScreenerNews.prototype.daysArray = [
	"Sunday",
	"Monday",
	"Tuesday",
	"Wednesday",
	"Thursday",
	"Friday",
	"Saturday"
]

ScreenerNews.prototype.monthsArray = [
	"January",
	"February",
	"March",
	"April",
	"May",
	"June",
	"July",
	"August",
	"September",
	"October",
	"November",
	"December"
]

ScreenerNews.prototype.formatDMDate = function(date) {	
	var dateTime = date.split(" ");
	var date = dateTime[0];
	var dateParts = date.split("-");
	var d = new Date();
	d.setYear(dateParts[0]);
	d.setMonth(Number(dateParts[1]) - 1);
	d.setDate(dateParts[2]);
	
	return this.daysArray[d.getDay()] + ",<br />" + this.monthsArray[d.getMonth()] + " " + d.getDate();
}

ScreenerNews.prototype.makeTransparentPng = function(img) {

	var IE6 = /msie|MSIE 6/.test(navigator.userAgent);
	if(!IE6) { return; }
	
	var imgName = img.src.toUpperCase();
	if (imgName.substring(imgName.length-3, imgName.length) == "PNG") {
		var imgID = (img.id) ? "id='" + img.id + "' " : "";
		var imgClass = (img.className) ? "class='" + img.className + "' " : "";
		var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
		var imgStyle = "display:inline-block;" + img.style.cssText ;
		if (img.align == "left") {
			imgStyle = "float:left;" + imgStyle;
		}
		if (img.align == "right") {
			imgStyle = "float:right;" + imgStyle;
		}
		if (img.parentElement.href) {
			imgStyle = "cursor:hand;" + imgStyle;
		}
		var strNewHTML = "<span " + imgID + imgClass + imgTitle
			+ " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
			+ "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
			+ "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>" 
		img.outerHTML = strNewHTML;
	}
}


ScreenerNews.prototype.draw = function(e, el, result) {	
	var elXY = Element.getXY(el);

	if(ScreenerNews.containers.length) {
		for(var i=ScreenerNews.containers.length-1; i>=0; i--) {
			Element.remove(ScreenerNews.containers[i]);
		}
		ScreenerNews.containers = [];
	}
	
	var content, img;
	var container = Element.create("div",{className:"news-results-container"},[
		content = Element.create("div",{className:"content"},
			Element.create("h2",{},"FT Recent News")
		),
		img = Element.create("img",{src:"../resources/image/newscarat.png", className:"carat", width:'22', height:'23'}),
		Element.create("div",{className:"shadow"})
	])
	
	var anchors = [], thisA;
	
	if(!result.length) {
		Element.addChild(content,"There are no news stories available");
	} else {

		var ul = Element.create("ul",{className:"news-list"});
		for(var i=0; i<result.length; i++) {
			var thisResult = result[i];
			Element.addChild(ul,
				Element.create("li",{},[
					Element.create("div",{className:"date"},this.formatDMDate(thisResult.DocumentDate)),
					Element.create("div",{className:"headline"},
						thisA = Element.create("a",{href:thisResult.URLOfDoc},thisResult.Headline)
					)
				])
			);
			
			anchors.push(thisA);
		}
		Element.addChild(content,ul);
		Element.create("br",{className:"clear"},null,content);
	}
	
	Element.addChild(document.body,container);
	Element.setXY(container,elXY.x - 10, elXY.y + 14);
	Events.add({
		element:container,
		type: "click",
		handler: function(e, el) {
			Events.cancel(e);
		},
		context: this
	});
	
	Events.add({
		element:anchors,
		type: "click",
		handler: function(e, el) {
			Events.cancel(e);
			window.open(el.getAttribute("href"));
		},
		context: this
	});
	
	
	this.makeTransparentPng(img);
	ScreenerNews.containers.push(container);
}
/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/Paging.js
*/
/*
	Usage:
		After instantiating this object, you must call three functions before it will function correctly, they are:
		
			.setContentContainer()
			.setBufferLoadFunction()
			.init() or .draw()
		
		.setContentContainer() must be passed the parent element that contains the paging and the content that is being rendered per page.
		
		.setBufferLoadFunction() must be passed your content buffer call exactly as you would pass it to a .load call on ContentBuffer.
		
		.init() or .draw() must be called to attach events to the rendered paging.
		
		If you are using this in conjunction with the server side version, pass in zero parameters to the constructor.  This library will grab all the key values from the previously rendered paging.
  		
		Here's an example usage:
		
			if NOT using server side paging:
				var p = new Paging({r: currentRow, t: totalRows, n: numRowsPerPage});
				- or -
				var p = new Paging(currentRow, totalRows, numRowsPerPage);
			
			if using server side paging:
				var p = new Paging();
				
				p.setContentContainer(Element.get("wsod"));
				p.setBufferLoadFunction({
					url: "PagingTest_buffer.asp",
					method: "post",
					contentType: "text/html",
					data: {
						wsodIssue: 572009
					},
					debug: true,
					onload: this.outputResults,
					context: this
				});
				p.init();
				
		If you want to disable the loading graphic, call the following:
		
			p.showLoading(false);
*/
var Paging = function() {
	var currentRow, totalRows, numRowsPerPage;
	
	if (arguments.length > 1) {
		currentRow = arguments[0];
		totalRows = arguments[1];
		numRowsPerPage = arguments[2] || this.DEFAULT_ROWS_PER_PAGE;
	} else if (1 == arguments.length && "object" == typeof arguments[0]) {
		currentRow = arguments[0].r;
		totalRows = arguments[0].t;
		numRowsPerPage = arguments[0].n || this.DEFAULT_ROWS_PER_PAGE;
	}

	this.setRowsPerPage(numRowsPerPage);
	this.setCurrentRow(currentRow);
	this.setTotalRows(totalRows);
	this.showLoading(true);
}

Paging.prototype.DEFAULT_ROWS_PER_PAGE = 25;
Paging.prototype.DEFAULT_URL = "javascript:void(0)";
Paging.prototype.VISIBLE_PAGES = 5;
Paging.prototype.CSS_PAGING_LEFT_ACTIVE = "nav-icon nav-left-active";
Paging.prototype.CSS_PAGING_RIGHT_ACTIVE = "nav-icon nav-right-active";
Paging.prototype.CSS_PAGING_LEFT_INACTIVE = "nav-icon nav-left-inactive";
Paging.prototype.CSS_PAGING_RIGHT_INACTIVE = "nav-icon nav-right-inactive";

Paging.prototype.showLoading = function(show) {
	if (undefined != show) {
		this._showLoading = show;
	}
	
	return this._showLoading || false;
}

Paging.prototype.getContentContainer = function() { return document.body; }
Paging.prototype.setContentContainer = function(elContainer) {
	this.getContentContainer = function() {
		return "string" == typeof elContainer ? Element.get(elContainer) : elContainer || document.body;
	}
	
	this.setPagingContainer();
}

Paging.prototype.getPagingContainer = function() { return null; }
Paging.prototype.setPagingContainer = function(container) {
	var container = container || Element.parseSelector("div.pagingNavigation", this.getContentContainer(), "first");
	
	if (container) {
		this.getPagingContainer = function() {
			return container;
		}
		
		if (!this.getCurrentRow() && !this.getTotalRows()) {
			this.setRowsPerPage(this.getPagingContainer().getAttribute("rowsPerPage"));
			this.setCurrentRow(this.getPagingContainer().getAttribute("currentRow"));
			this.setTotalRows(this.getPagingContainer().getAttribute("totalRows"));	
		}
	}
}

Paging.prototype.getBufferLoadFunction = function() { alert('setBufferLoadFunction must be called.'); return null; }
Paging.prototype.setBufferLoadFunction = function(loadParams) {
	var onloadFunction = loadParams.onload || function() {};
	var onloadContext = loadParams.context || window;
	
	loadParams = loadParams || {};
	loadParams.data = loadParams.data || {};
	loadParams.onload = function(cb) {
		onloadFunction.Context(onloadContext)(cb);
		
		if (this.showLoading()) { this.removeLoading(); }
		this.remove();

		Element.addChild("wsod", this.draw());
		
		MouseHover.Symbol.init();
	}.Context(this);

	this.getBufferLoadFunction = function() {
		return loadParams;
	}
}

Paging.prototype.getPageContent = function(e, el) {
	var rowsPerPage = this.getRowsPerPage();
	var page = Number(el.getAttribute("page"));
	
	this.setCurrentRow(rowsPerPage * (page - 1) + this.getBaseRow());

	var loadParams = this.getBufferLoadFunction();
		loadParams.data.startRow = this.getCurrentRow();

	if (this.showLoading()) { this.drawLoading(); }
		
 	this.getContentBuffer().abortRequests();
 	this.getContentBuffer().load(loadParams);
}

Paging.prototype.drawLoading = function() {
	var contentContainer = this.getContentContainer();
	var contentContainerSize = Element.getSize(contentContainer);
	var pagingContainer = this.getPagingContainer();
	var pagingContainerSize = Element.getSize(pagingContainer);
	
	// this feels risky, but for the loading functionality to work correctly, the container needs to be position: relative
	if (!contentContainer.style.position) {
		contentContainer.style.position = "relative";
	}
	
	var loadingImageContainerEl;
	var loadingEl = Element.create("div", {"class":"loadingContainer wsodHidden"}, [
		loadingImageContainerEl = Element.create("div", {"class":"loadingImageContainer"}, [
			Element.create("div", {"class":"loadingImage"}, "&nbsp;")
			//,Element.create("div", {"class":"loadingText"}, "Loading...")
		])
	], contentContainer);
	
	var loadingImageContainerElSize = Element.getSize(loadingImageContainerEl);
	
	Element.setSize(loadingEl, contentContainerSize.width, contentContainerSize.height);
	Element.setXY(loadingImageContainerEl, null, (contentContainerSize.height / 2) - (loadingImageContainerElSize.height / 2));
	Element.removeClass(loadingEl, "wsodHidden");
}

Paging.prototype.removeLoading = function() {
	var loadingEl = Element.parseSelector("div.loadingContainer", this.getContentContainer(), "first");
	
	if (loadingEl) {
		Element.remove(loadingEl);
	}
}

Paging.prototype.getCurrentRow = function() { return null; }
Paging.prototype.setCurrentRow = function(row) {
	this.setBaseRow(row);

	this.getCurrentRow = function() {
		return row;
	}
}

Paging.prototype.getBaseRow = function() { return null; }
Paging.prototype.setBaseRow = function(row) {
	var baseRow = row ? row % this.getRowsPerPage() : null;

	this.getBaseRow = function() {
		return baseRow;
	}
}

Paging.prototype.getRowsPerPage = function() { return null; }
Paging.prototype.setRowsPerPage = function(rows) {
	this.getRowsPerPage = function() {
		return rows;
	}
}

Paging.prototype.getTotalRows = function() { return null; }
Paging.prototype.setTotalRows = function(rows) {
	this.getTotalRows = function() {
		return rows;
	}
}

Paging.prototype.getCurrentPage = function() {
	var currentRow = this.getCurrentRow();
	var rowsPerPage = this.getRowsPerPage();
	
	var currentPage = Math.floor(currentRow / rowsPerPage) + 1;

	return currentPage;
}

Paging.prototype.getStartPage = function() {
	var numPages = this.getNumPages();
	var currentPage = this.getCurrentPage();
	var midPoint = Math.round(this.VISIBLE_PAGES / 2);
	
	var startPage;
	
	if (currentPage <= midPoint) {
		startPage = 1;
	} else if (currentPage >= numPages - midPoint + 1) {
		startPage = numPages - this.VISIBLE_PAGES + 1;
	} else {
		startPage = currentPage - midPoint + 1;
	}
	
	return startPage;
}

Paging.prototype.getEndPage = function() {
	var numPages = this.getNumPages();
	var currentPage = this.getCurrentPage();
	var midPoint = Math.round(this.VISIBLE_PAGES / 2);
	
	var endPage;
	
	if (currentPage <= midPoint) {
		endPage = numPages < this.VISIBLE_PAGES ? numPages : this.VISIBLE_PAGES;
	} else if (currentPage >= numPages - midPoint + 1) {
		endPage = numPages;
	} else {
		endPage = currentPage + midPoint - 1;
	}
	
	return endPage;
}

Paging.prototype.getNumPages = function() {
	var perPage = this.getRowsPerPage();
	var totalRows = this.getTotalRows();
	
	var numPages = Math.ceil(totalRows / perPage);
	
	return numPages;
}

Paging.prototype.getPreviousLink = function() {
	var startPage = this.getStartPage();
	var currentPage = this.getCurrentPage();
	
	var targetPage = Math.max(currentPage - 1, startPage);
	
	var previousLink;
	if (startPage == currentPage) {
		previousLink = Element.create("div", {"class":this.CSS_PAGING_LEFT_INACTIVE});
	} else {
		previousLink = Element.create("a", {"class":this.CSS_PAGING_LEFT_ACTIVE, "href":"javascript:void(0)", "page": targetPage});
	}
	
	return previousLink;
}

Paging.prototype.getNextLink = function() {
	var endPage = this.getEndPage();
	var currentPage = this.getCurrentPage();
	
	var targetPage = Math.min(currentPage + 1, endPage);
	
	var nextLink;
	if (endPage == currentPage) {
		nextLink = Element.create("div", {"class":this.CSS_PAGING_RIGHT_INACTIVE});
	} else {
		nextLink = Element.create("a", {"class":this.CSS_PAGING_RIGHT_ACTIVE, "href":"javascript:void(0)", "page": targetPage});
	}
	
	return nextLink;
}

Paging.prototype.getContent = function() {
	var content = Element.parseSelector("div.pagingNavigation", this.getContentContainer(), "first");
	
	if (!content) {
		var currentRow = this.getCurrentRow();
		var totalRows = this.getTotalRows();
		var rowsPerPage = this.getRowsPerPage();
		var currentPage = this.getCurrentPage();
		
		var nextLink, previousLink;
		var content = Element.create("div", {"class":"pagingNavigation"}, [
			nextLink = this.getNextLink(),
			previousLink = this.getPreviousLink(),
			Element.create("div", {"class":"pagingKey"}, [
				Element.create("span", {}, (currentRow + (this.getBaseRow() ? 0 : 1)) + "-" + Math.min(rowsPerPage * currentPage, totalRows)),
				" of " + totalRows + " results"
			])
		], this.getContentContainer());
		
		var pagingLinks = [];
		if ("A" == nextLink.tagName) { pagingLinks.push(nextLink); }
		if ("A" == previousLink.tagName) { pagingLinks.push(previousLink); }
		
		this.getPagingLinks = function() {
			return pagingLinks;
		}
	}
	
	this.setPagingContainer(content);
	
	return content;
}

Paging.prototype.getPagingLinks = function() {
	return Element.parseSelector("a", this.getPagingContainer());
}

Paging.prototype.draw = function() {
	var content = this.getContent();
	
	this.getEventManager().add(this.getPagingLinks(), "click", this.getPageContent, this);	
}

Paging.prototype.init = Paging.prototype.draw;

Paging.prototype.remove = function() {
	this.getEventManager().removeAll();

	Element.removeChildNodes(this.getPagingContainer());
}

Paging.prototype.getContentBuffer = function() {
	var cb = new ContentBuffer();
	
	this.getContentBuffer = function() {
		return cb;
	}
	
	return this.getContentBuffer();
}

Paging.prototype.getEventManager = function() {
	var em = new EventManager();
	
	this.getEventManager = function() {
		return em;
	}
	
	return this.getEventManager();
}
/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/Effects.1.js
*/
// FX!

Effects_class = function () {
	this.namedQueues = { };
	this.globalQueue = [ ];
}

Effects_class.prototype.enqueue = function (effectList, params) {
	if (!params) {
		params = { };
	}

	var global = params.global || false;
	var qName = params.global ? null : (params.shared || 'r'+Math.random());

	if (qName && !this.namedQueues[qName]) {
		this.namedQueues[qName] = [ ];
		this.namedQueues[qName].name = qName;
	}
	var queue = qName ? this.namedQueues[qName] : this.globalQueue;

	if (params.onComplete) {
		if (params.context) {
			queue.onComplete = function () { params.onComplete.apply(params.context, [ ]); }
		} else {
			queue.onComplete = params.onComplete;
		}
	}

	for (var i = 0; i < effectList.length; i++) {
		queue.push(effectList[i]);
	}

	this._runQueue(queue);
}

Effects_class.prototype.createParallel = function (effectList, params) {
	var onComplete = null;
	if (params) {
		if (params.onComplete) {
			if (params.context) {
				onComplete = function () { params.onComplete.apply(params.context, [ ]); }
			} else {
				onComplete = params.onComplete;
			}
		}
	}

	var InitClosure = function(context) {
		return function() {
			context._initParallel(effectList, onComplete);
		};
	};
		
	effectList.animate = InitClosure(this);
	return effectList;
}

Effects_class.prototype.runParallel = function (effectList, params) {
	var ef = this.createParallel(effectList, params);
	ef.animate();
	return ef;
}

Effects_class.prototype.create = function (element, type, params) {
	var ef = new Effect_class(element, type, params);
	return ef;
}

Effects_class.prototype.run = function (element, type, params) {
	var ef = this.create(element, type, params);
	ef.animate();
	return ef;
}

Effects_class.prototype._runQueue = function (queue) {
	if (queue.length) {
		var ef = queue.shift();
		ef.runningQueue = queue;
		ef.animate();
	} else {
		if (queue.onComplete) {
			queue.onComplete();
			queue.onComplete = null;
		}
		if (queue.name) {
			// this doesn't get called when queueing a parallel effect??
			delete this.namedQueues[queue.name];
		}
	}
}

Effects_class.prototype._initParallel = function (effectList, onComplete) {
	for (var i = 0; i < effectList.length; i++) {
		effectList[i].animateParallel();
	}

	this._animateParallel(effectList, onComplete);
}

Effects_class.prototype._animateParallel = function (effectList, onComplete) {
	var isAnimating = false;
	for (var i = 0; i < effectList.length; i++) {
		effectList[i].nextFrame();
		isAnimating = isAnimating || effectList[i].isAnimating;
	}

	if (isAnimating) {
		var ParaClosure = function(context) {
			return function() {
				context._animateParallel(effectList, onComplete);
			};
		};
			
		setTimeout(ParaClosure(this), 0);
	} else {
		if (effectList.runningQueue) {
			this._runQueue(effectList.runningQueue);
			effectList.runningQueue = null;
		}

		if (onComplete) {
			onComplete();
		}
	}
}

Effects = new Effects_class();

/*-----------------------------------------------------------------------------------
Effect:

var effect = new Effect([oDomElement|sID],{type:sType,to:int},iDuration(in seconds));
effect.animate();

Borrowed from:

TERMS OF USE - EASING EQUATIONS
Open source under the BSD License.
Copyright (c) 2001 Robert Penner
JavaScript version copyright (C) 2006 by Philippe Maegerman
All rights reserved.

-------------------------------------------------------------------------------------*/

var Effect_class = function(oEl,sType,oParams) {
	
	//Default argument values
	oParams = oParams || false;
	
	if(!oParams) {
	
		return;
		
	}
	
	//Constants
	
	this.oEl = Element.get(oEl);
	
	this._animType = sType || false;
	
	this.valueGetter = this.getValueGetterSetters().getter;
	
	this.valueSetter = this.getValueGetterSetters().setter;
	
	this._rawTo = oParams.to;
	
	this._rawFrom = oParams.from !== undefined ? oParams.from : this.valueGetter();
	
	this._easing = Easing; 
	
	this._easeMethod = oParams.easing && this._easing[oParams.easing] && this._easing[oParams.easing] !== undefined ? this._easing[oParams.easing] : this._easing.easeNone;
	
	this._duration = oParams.duration;
	
	this.isAnimating = false;
	
	this.setOnCompleteHandler(oParams.onComplete, oParams.context);
	
	//Time
	
	this._startTime = 0;
	
	this._prevTime = 0;
	
	this._time = 0;
	
}



Effect_class.prototype.animate = function(){
	
	this.animateParallel();

	this.onEnterFrame();
	
}

Effect_class.prototype.animateParallel = function(){
	this._to = (typeof this._rawTo == 'function') ? this._rawTo() : this._rawTo;
	this._from = (typeof this._rawFrom == 'function') ? this._rawFrom() : this._rawFrom;
	
	// So far backgorund is the only array
	// may have to figure out a more generic way to do this in the future.
	if (this._animType == 'background') {
		if (!(this._to instanceof Array)) {
			this._to = this.toRGB(this._to);
		}
		if (!(this._from instanceof Array)) {
			this._from = this.toRGB(this._from);
		}
	}

	this._delta = this.getDelta();
	
	this._startTime = new Date().getTime();
	
	this.isAnimating = true;

	// parallel animation calls nextFrame() explicitly
	//this.onEnterFrame();
	
}

Effect_class.prototype.onEnterFrame = function() {

	if(this.isAnimating) {
		
		this.nextFrame();
		
		var AnimClosure = function(context) {
			return function() {
				context.onEnterFrame()
			};
		};
		
		setTimeout(AnimClosure(this), 0);
		
	}

}

Effect_class.prototype.nextFrame = function() {

	this.setTime((this.getTimer() - this._startTime) / 1000);
	
}

Effect_class.prototype.getTimer = function() {

	return new Date().getTime() - this._time; 

}

Effect_class.prototype.setTime = function(t){
	
	this._prevTime = this._time;
	
	if (t > this._duration) {
		
		this._time = this._duration;
		
		this.update();
		
		this.stop();
		
	}  else {
		
		this._time = t;
		
		this.update();
		
	}
}

Effect_class.prototype.update = function(value) {

	if (this._from instanceof Array) {
		this.valueSetter([  this._easeMethod(this._time,this._from[0],this._delta[0],this._duration),
							this._easeMethod(this._time,this._from[1],this._delta[1],this._duration),
							this._easeMethod(this._time,this._from[2],this._delta[2],this._duration)
						]);
	} else {
		this.valueSetter(this._easeMethod(this._time,this._from,this._delta,this._duration));
	}
	
}
	
Effect_class.prototype.stop = function() {
	
	this.isAnimating = false;
	
	if (this.runningQueue) {
		Effects._runQueue(this.runningQueue);
		this.runningQueue = null;
	}

	this.onComplete();

}

Effect_class.prototype.getDelta = function(){
	
	return (this._to instanceof Array) ? 
		[ this._to[0] - this._from[0],this._to[1] - this._from[1],  this._to[2] - this._from[2] ] :
		this._to - this._from;
	
}

Effect_class.prototype.setOnCompleteHandler = function(f,c){
	if (c && f) {
		this.onComplete = function () { f.apply(c, arguments) };
	} else {
		this.onComplete = f || function(){return false;}; 
	}
}

/*
return a setter/getter function for oEl:
if you pass it a value, it will set that value for this.oEl and return it, if you dont, it will just return the
current value for oEl
*/
Effect_class.prototype.getValueGetterSetters = function() {

	var oGS; //{getter:,setter:,object} 

	switch(this._animType) {
	
		case "width":

			return {
				getter:function() {	
					return Element.getSize(this.oEl).width
				},
				setter:function(iWidth) {
					iWidth = iWidth >= 0 ? iWidth : 0;
					Element.setWidth(this.oEl,iWidth);
				}
			}
		
		break;
		case "height":
		
			return {
				getter:function() {	
					return Element.getSize(this.oEl).height
				},
				setter:function(iHeight) {
					iHeight = iHeight >= 0 ? iHeight : 0;
					Element.setHeight(this.oEl,iHeight);
				}
			}
		
		break;
		/*
		case "x":
			
			return {
				getter:function() {	
					return Element.getXY(this.oEl).x
				},
				setter:function(iX) {
					var iY = Element.getXY(this.oEl).y
					Element.setXY(this.oEl,iX,iY);
				}
			}
		
		break;
		case "y":
			
			return {
				getter:function() {	
					return Element.getXY(this.oEl).y
				},
				setter:function(iY) {
					var iX = Element.getXY(this.oEl).x
					Element.setXY(this.oEl,iX,iY);
				}
			}
		
		break;
		*/
		case "x":
			
			return {
				getter:function() {	
					return this.oEl.offsetLeft;
				},
				setter:function(iX) {
					this.oEl.style.left = iX + "px";
				}
			}
		
		break;
		case "y":
			
			return {
				getter:function() {	
					return this.oEl.offsetTop;
				},
				setter:function(iY) {
					this.oEl.style.top = iY + "px";
				}
			}
		
		break;
		case "opacity":
		
			return {
				getter:function() {	
					var iOpac = this.oEl.style.opacity;
					return iOpac == "" || isNaN(iOpac) ? 100 : iOpac * 100;
				},
				setter:function(iOpacity) {
					Element.setOpacity(this.oEl,iOpacity);
				}
			}
		
		break;
		case "scrollLeft":
		
			return {
				getter:function() {	
					return this.oEl.scrollLeft;
				},
				setter:function(iScrollLeft) {
					this.oEl.scrollLeft = iScrollLeft;
				}
			}
		
		break;
		case "scrollTop":
		
			return {
				getter:function() {	
					return this.oEl.scrollTop;
				},
				setter:function(iScrollTop) {
					return this.oEl.scrollTop = iScrollTop;
				}
			}
		case "background":
		
			return {
				getter:function() {	
					return this.toRGB(this.oEl.style.backgroundColor);
				},
				setter:function(aRGB) {
					this.oEl.style.backgroundColor = this.toHex(aRGB);
					return aRGB
				}
			}
		
		break;
		default:
			return false;
		break
	
	}
}

Effect_class.prototype.toRGB = function (hex) {
	hexInt = parseInt(hex.substr(1), 16);
	return [ hexInt >> 16, hexInt >> 8 & 255, hexInt & 255 ];
}

Effect_class.prototype.toHex = function (rgb) {
	var hex = '#';
	for (var i = 0; i < 3; i++) {
		rgb[i] = Math.min(255, Math.max(0, Math.round(rgb[i]))).toString(16);
		while (rgb[i].length < 2) {
			rgb[i] = '0' + rgb[i];
		}
		hex += rgb[i];
	}

	return hex;
}

/*-------------------------------------------------------------------
Easing
-------------------------------------------------------------------*/
var Easing = {};

Easing.easeNone =  function (t, b, c, d) {
   	return c*t/d + b;
}

Easing.backEaseIn = function(t,b,c,d,a,p){
	if (s == undefined) var s = 1.70158;
	return c*(t/=d)*t*((s+1)*t - s) + b;
}
Easing.backEaseOut = function(t,b,c,d,a,p){
	if (s == undefined) var s = 1.70158;
	return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
}
Easing.backEaseInOut = function(t,b,c,d,a,p){
	if (s == undefined) var s = 1.70158; 
	if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
	return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
}
Easing.elasticEaseIn = function(t,b,c,d,a,p){
		if (t==0) return b;  
		if ((t/=d)==1) return b+c;  
		if (!p) p=d*.3;
		if (!a || a < Math.abs(c)) {
			a=c; var s=p/4;
		}
		else 
			var s = p/(2*Math.PI) * Math.asin (c/a);
		
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	
}
Easing.elasticEaseOut = function (t,b,c,d,a,p){
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (!a || a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b);
	}
Easing.elasticEaseInOut = function (t,b,c,d,a,p){
	if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) var p=d*(.3*1.5);
	if (!a || a < Math.abs(c)) {var a=c; var s=p/4; }
	else var s = p/(2*Math.PI) * Math.asin (c/a);
	if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
}

Easing.bounceEaseOut = function(t,b,c,d){
	if ((t/=d) < (1/2.75)) {
		return c*(7.5625*t*t) + b;
	} else if (t < (2/2.75)) {
		return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
	} else if (t < (2.5/2.75)) {
		return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
	} else {
		return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
	}
}
Easing.bounceEaseIn = function(t,b,c,d){
	return c - Easing.bounceEaseOut (d-t, 0, c, d) + b;
	}
Easing.bounceEaseInOut = function(t,b,c,d){
	if (t < d/2) return Easing.bounceEaseIn (t*2, 0, c, d) * .5 + b;
	else return Easing.bounceEaseOut (t*2-d, 0, c, d) * .5 + c*.5 + b;
	}

Easing.strongEaseInOut = function(t,b,c,d){
	return c*(t/=d)*t*t*t*t + b;
	}

Easing.regularEaseIn = function(t,b,c,d){
	return c*(t/=d)*t + b;
	}
Easing.regularEaseOut = function(t,b,c,d){
	return -c *(t/=d)*(t-2) + b;
	}

Easing.regularEaseInOut = function(t,b,c,d){
	if ((t/=d/2) < 1) return c/2*t*t + b;
	return -c/2 * ((--t)*(t-2) - 1) + b;
	}
Easing.strongEaseIn = function(t,b,c,d){
	return c*(t/=d)*t*t*t*t + b;
	}
Easing.strongEaseOut = function(t,b,c,d){
	return c*((t=t/d-1)*t*t*t*t + 1) + b;
	}

Easing.strongEaseInOut = function(t,b,c,d){
	if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
	return c/2*((t-=2)*t*t*t*t + 2) + b;
	}



/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/Slider.1.js
*/
/*
 *  Slider_Class
 *  SliderHandle_Class
 *
 *	Purpose: 
 *  To create a sliding element on your page where the value of one or more sliding handles 
 *  along a bar changes with a mouse move/drag or keyboard arrow stroke.
 *  (This script should work in all browsers.)
 *
 *  By Melissa Fedak, Summer 2008 (with thanks to Adam Shamblin for help and examples)
 *
 *	See  dev2.wallst.com/playground/melf/sliders/slidertest.html  for a variety of uses
 *  See  dev2.wallst.com/playground/melf/sliders/tests/exampleUsage1.html  for below Example Usage 1 in action
 *  See  dev2.wallst.com/playground/melf/sliders/tests/exampleUsage2.html  for below Example Usage 2 in action
 *
 *
 *	REQUIRED SCRIPTS:
 * 	<script type="text/javascript" src="/includes/jslib/wsdom/wsdom.js"></script>
 *	<script type="text/javascript" src="/includes/jslib/wsdom/console/console.1.js"></script>
 *	<script type="text/javascript" src="/includes/jslib/wsdom/events/events.3.js"></script>
 *	<script type="text/javascript" src="/includes/jslib/wsdom/element/element.3.js"></script>
 *	<script type="text/javascript" src="/includes/jslib/wsdom/wsdom.deployment.classic.js"></script> 
 *
 *
 ****** EXAMPLE USAGE 1 (minimum required to create a slider):
 *
 *		<script type="text/javascript">	
 *			var slider  = new Slider_Class()
 * 			var handle = new SliderHandle_Class()
 *			slider.addHandle(handle)
 * 		</script>
 *
 *
 ****** EXAMPLE USAGE 2 (including all code and using all parameters):
 *	
 *	 	<style type="text/css">	
 *			#parentDiv .sliderBarClass {
 *				background-color:#999;
 *				width:15px;
 *				height:200px;
 *			}
 *			#parentDiv .sliderHandleClass {
 *				background-color:#CC3;
 *				width:21px;
 *				height:15px;
 *				left:-3px;
 *	 			font-size:1px;
 *				cursor:pointer;
 *			}	
 *			#parentDiv .sliderHandleClass0 {
 *				background-color:#3CC;
 *			}
 *		</style>
 * 
 *		<div id="parentDiv"></div>
 *
 *	 	<script type="text/javascript">
 *	  var slider  = new Slider_Class({
 *			parentID:"parentDiv"
 *			,sliderClass:"sliderBarClass"
 *			,orientation: "topToBottom" //can be: "leftToRight" "rightToLeft" "topToBottom" "bottomToTop"
 *			,handleOverlap: "handleEdge" //can be: "handleEdge" "all" "nextPixel" "5" (number of pixels barrier)
 *			,minVal:-100
 * 			,maxVal:100 
 *			,handleOffset:[7,8] //7 is top/left offset, 8 is bottom/right.  7+8 = handle height 15.
 *       //Note: if height (width if horizontal) is even, this can be a single number
 *		});
 *
 *	  var handle1 = new SliderHandle_Class({
 *			increment:10    // how much arrow key will move handle; also can be used for plus/minus buttons
 *			,defaultVal:-20
 *			,tabindex:"1"
 *			,handleClassName:"sliderHandleClass" //recommend that this be the same for all handles.  
 *				// There will already be a unique class created for each with a number after it, i.e. 'sliderHandleClass0'
 *		})
 *
 *	  var handle2 = new SliderHandle_Class({ // No parameters actually required; all have default values
 *			increment:10  // how much arrow key will move handle; also can be used for plus/minus buttons
 *			,defaultVal:30
 *			,tabindex:"2"   //recommend that this be exactly one more than the previous handle's tabindex
 *			,handleClassName:"sliderHandleClass"  //recommend that this be the same for all handles. 
 *					// There will already be a unique class created for each with a number after it, i.e. 'sliderHandleClass1'
 *		})
 *
 *	  slider.addHandle(handle1,handle2); //Handles should be in order from left to right or top to bottom.
 *
 ****** END EXAMPLE USAGE
 *
 *
 *  CURRENT LIMITATIONS: 
 *  - No borders: since borders are not included as part of width consistently in browsers, they don't work properly.
 *  - Slider handle: The *center* of the slider handle always represents the current value along the bar.
 *  - Multiple handles that do not overlap must be created in the order they appear on the screen. 
 *    Also, if the defaults are not consistent with that order, the handles will jump when they touch other handles.
 *  - For multiple handles, the no-overlap only works with linear handles (not if handles are on both sides of the bar)
 *
 */


function Slider_Class(oData) {
	
	this.oData = oData || {};
	
	this.parentID = 	this.oData.parentID ? this.oData.parentID : "";
	this.parentEl = 	this.oData.parentEl || (this.parentID != "" ? Element.get(this.parentID) : Element.create("div",{},[],document.getElementsByTagName("body")[0]));
	
	this.sliderClass = this.oData.sliderClass ? this.oData.sliderClass : "sliderBar";
	this.sliderSpan = this.oData.sliderSpan || false;
	
	this.criteria = this.oData.criteria || false;

	this._initNumbers();
	this._init();
	
}

Slider_Class.prototype._init = function() {

	this.handles = [];
	this.handlesLen = 0;

	this.orientation = this.oData.orientation ? this.oData.orientation : "leftToRight";
	this.isVertical =  this.orientation == "topToBottom" || this.orientation == "bottomToTop";
	this.isBackwards =  this.orientation == "bottomToTop" || this.orientation == "rightToLeft";
	
	this.handleOverlap = this.oData.handleOverlap ? this.oData.handleOverlap : "handleEdge";

	this._drawSliderBar();

	this._calculateMagicNumbers();

}

Slider_Class.prototype._initNumbers = function() {

	//Defaults 0-100
	this.maxVal = !isNaN(parseFloat(this.oData.maxVal)) ? parseFloat(this.oData.maxVal) : 100;
	this.minVal = !isNaN(parseFloat(this.oData.minVal)) ? parseFloat(this.oData.minVal) : 0;
	
	this.handleOffsetHigh	= 0;
	this.handleOffsetLow = 0;

	if (this.oData.handleOffset) {
		if (typeof(this.oData.handleOffset) == "object") {
			this.handleOffsetLow = this.oData.handleOffset[0] ? this.oData.handleOffset[0] : this.handleOffsetLow;
			this.handleOffsetHigh = this.oData.handleOffset[1] ? this.oData.handleOffset[1] : this.handleOffsetHigh;
		}
		else if(!isNaN(parseInt(this.oData.handleOffset))) {
			this.handleOffsetLow = parseInt(this.oData.handleOffset);
			this.handleOffsetHigh = this.handleOffsetLow;
		}
	}
}

Slider_Class.prototype._drawSliderBar = function() {

	this.sliderBar = Element.create("div",{className:this.sliderClass,style:"position:relative"},null,this.parentEl)
	this.sliderBox = this.sliderSpan ? Element.create("div",{className:"sliderBox"}, null, this.sliderBar) : false;

	this._setDefaults();
}

Slider_Class.prototype._calculateMagicNumbers = function() {

	if (this.isVertical) {
		
		this.offsetFromEdge = Element.getXY(this.sliderBar).y; //distance from window edge to slider bar top edge. For events.
		this.barLength = Element.getSize(this.sliderBar).height;

	} else {
		
		this.offsetFromEdge = Element.getXY(this.sliderBar).x; //distance from window edge to slider bar left edge. For events.
		this.barLength = Element.getSize(this.sliderBar).width;
	
	}
	
	this.minPix = 0;
	this.maxPix = this.barLength  - (this.handleOffsetLow+this.handleOffsetHigh);

	this.valuePerPixel = this.maxPix ? (this.maxVal - this.minVal) / this.maxPix : 1;
	this.pixelPerValue = this.valuePerPixel ? (1 / this.valuePerPixel) : 1;
}

Slider_Class.prototype._setDefaults = function() {
	
	//Figure that if height is not set, then nothing likely is and we should set some defaults
	//(I can't check against width since it is auto-set based off the parent width)
	if (!Element.getSize(this.sliderBar).height) {
		Element.setHeight(this.sliderBar,this.isVertical ? 100 : 10);
		Element.setWidth(this.sliderBar,this.isVertical ? 10 : 100);
		this.sliderBar.style.backgroundColor = "#CCC";
		this.sliderBar.style.fontSize = "1px"; //Since IE can't seem to handle small heights sometimes...
	}
}

Slider_Class.prototype.addHandle = function() { //parameters should be Slider_Handles

	var handle;
	
	for(var i = 0, len = arguments.length; i < len; i++) {

		handle = arguments[i];

		if (handle.el) { //handle.el should exist if it the Slider_Handle was instantiated correctly
			this.handles.push(handle)
			Element.addChild(this.sliderBar, handle.el);
			handle.init(this,this.handlesLen);
      this.handlesLen++;
		}
	}
	
}




/*
 * SliderHandle_Class. 
 * Initialized first in asp/html constructor, then more values initialized when addHandle() is called from slider bar
 *
 */

function SliderHandle_Class(oData) {
	
	this._preInit(oData);
	this.drawHandle();

}

// This function does nothing here.  It exists to be overridden.

SliderHandle_Class.prototype.MyUpdateValue = function(mouseEvent, direction) {
	 
	 //This function is called at the end of every mouse or keyboard event.  
	 //Override it to perform actions when value of slider handle is updated.
	 //
	 // PARAMETERS:
	 //  mouseEvent can be: "mousestart" "mousemove" "mouseend" or "keydown"
	 //  direction can be: "up" "down" or null.  "up" and "down" refer to value, not position.
	 //
	 //Use this function to update a dynamic text value with the current value or position of this handle
	 //Use "mouseend" to finalize value or position of handle (if you want to snap to a value after sliding is done for example)
}


// Called by constructor before handle is drawn

SliderHandle_Class.prototype._preInit = function (oData) { 
	
	this.oData = oData || {};
	
	this.defaultVal = !isNaN(parseFloat(this.oData.defaultVal)) ?  parseFloat(this.oData.defaultVal) : 0;
	this.increment = !isNaN(parseFloat(this.oData.increment)) ?  parseFloat(this.oData.increment) : 1;
	this.tabindex = this.oData.tabindex ? String(this.oData.tabindex) : "1"; //IE likes tabIndex to be a String
	this.handleClassName = this.oData.handleClassName ?  this.oData.handleClassName : "sliderHandle";
	this.coordMap = this.oData.coordMap ? this.oData.coordMap : null;
	this.valueMap = this.oData.valueMap ? this.oData.valueMap : {};
	
	this.handleLength = 1; // to be set after handle is drawn...
	this.halfOfHandle = 1; // to be set after handle is drawn...
	
	this.criteria = this.oData.criteria;

}


// Called from Slider_Class after handle is drawn

SliderHandle_Class.prototype.init = function (parentSliderBar, whichHandle) {  
	
	this.parentSliderBar = parentSliderBar; // link back up to parent slider bar
	this.whichHandle = whichHandle; // order within the handles (starts from 0)  Helpful if multiple handles
	
	Element.addClass(this.el,this.handleClassName+this.whichHandle); //gives each handle a unique class

	// Set min and max of the handle to start out the same as the min and max of the bar
	this.setMaxVal(this.parentSliderBar.maxVal);
	this.setMaxPix(this.parentSliderBar.maxPix);
	this.setMinVal(this.parentSliderBar.minVal);
	this.setMinPix(this.parentSliderBar.minPix);

	this._setDefaults();
	
	this.handleLength = this.parentSliderBar.isVertical ? Element.getSize(this.el).height : Element.getSize(this.el).width;
	this.halfOfHandle = Math.floor(this.handleLength / 2); // Helps make center of handle match value

	this.finalDisplayFromValue(this.defaultVal); // The main function that moves the handle to proper location

	Element.setVisibility(this.el,"visible"); //so handle doesn't appear to jump from 0 to default.

	this._initEvents();

}


// Creates the actual handle on the screen.

SliderHandle_Class.prototype.drawHandle = function() {

	this.el = Element.create("div",{className:this.handleClassName,tabIndex:this.tabindex,style:"position:absolute;visibility:hidden"})

}


// If width and height are not passed in, this sets some defaults so a slider handle gets drawn

SliderHandle_Class.prototype._setDefaults = function() {
	
	if (!Element.getSize(this.el).height || !Element.getSize(this.el).width) {
		Element.setSize(this.el, 10, 10);
		this.el.style.backgroundColor = "#C33"; //Figure if no height nor width is set, then bg probably isn't either
		this.el.style.fontSize = "1px"; //Since IE can't seem to handle small heights sometimes...
	}
	this._setZIndex(this.whichHandle);	
}

// Events and event-related functions initializer

SliderHandle_Class.prototype._initEvents = function () {
	
  this.mouseDownEvent = Events.add({
      type: 'mousedown',
      handler: this.startMoveHandler,
      context: this
  });

  this.mouseMoveEvent = Events.add({
      type: 'mousemove',
      handler: this.moveHandler,
      context: this
  });

  this.mouseUpEvent = Events.add({
      type: 'mouseup',
      handler: this.endMoveHandler,
      context: this
  });

  this.keyDownEvent = Events.add({
      type: 'keydown',
      handler: this.keyDownHandler,
      context: this
  });

  this.mouseDownEvent.addElement(this.el);
  this.keyDownEvent.addElement(this.el);
}


SliderHandle_Class.prototype.startMoveHandler = function (evt) {

  evt.cancel();

  this.mouseMoveEvent.addElement(document);
  this.mouseUpEvent.addElement(document);

	if (this.parentSliderBar.isVertical) {
  	this.eventCoord = isNaN(evt.nativeEvent.clientY) || evt.nativeEvent.clientY < 0 ? 0 : evt.nativeEvent.clientY;
	} else { 
  	this.eventCoord = isNaN(evt.nativeEvent.clientX) || evt.nativeEvent.clientX < 0 ? 0 : evt.nativeEvent.clientX;
  }	

	this._setZIndex(this.parentSliderBar.handlesLen); //Set moving slider to top
		
	this.findMouseOffset(this.eventCoord); //So mouse cursor doesn't jump to the center when slider starts moving
	
	if (this.parentSliderBar.handlesLen > 1) {
		this.multipleHandleMinMax(); //Adjust how far the slider handle can move based on location of other handles, if any
	}

	this.MyUpdateValue("mousestart",null);

}

SliderHandle_Class.prototype.moveHandler = function (evt) {

  evt.cancel();

	if (this.parentSliderBar.isVertical) {
	  	this.eventCoord = isNaN(evt.nativeEvent.clientY) || evt.nativeEvent.clientY < 0 ? 0 : evt.nativeEvent.clientY;	
	} else {
  		this.eventCoord = isNaN(evt.nativeEvent.clientX) || evt.nativeEvent.clientX < 0 ? 0 : evt.nativeEvent.clientX;
	}
	
	this.prevCurrentValue = this.currentValue; // for 'direction' parameter passed to MyUpdateValue()
	
	// Where we display the handle is based on first on the original window 'x' or 'y' coordinate clicked, then accounts for distance of bar from edge of window, then the distance of handle's offset from bar edge, and finally the distance of mouse from handle center (whew)
	this.finalDisplayFromPosition(
		this.eventCoord - 
		this.parentSliderBar.offsetFromEdge - 
		this.parentSliderBar.handleOffsetLow + 
		this.mouseOffset
	);
	
	this.MyUpdateValue(
		"mousemove",
		this.currentValue > this.prevCurrentValue
			? "up" 
			: this.currentValue < this.prevCurrentValue 
				? "down" 
				: null
	)
 }

SliderHandle_Class.prototype.endMoveHandler = function (e) {

  e.cancel();

  this.mouseMoveEvent.removeAllElements();
  this.mouseUpEvent.removeAllElements();

	this._setZIndex(this.whichHandle); //back to normal stacking order on the z-axis

  this.MyUpdateValue("mouseend",null);

}

SliderHandle_Class.prototype.keyDownHandler = function (evt, el) {
	
	var k = evt.nativeEvent;

	var keyNum = k.keyCode || k.charCode;

	if (this.KEYMAP[keyNum] == "rightArrowKey" || this.KEYMAP[keyNum] == "downArrowKey") {			
		if (this.parentSliderBar.handlesLen > 1) {
			this.multipleHandleMinMax()
		}
		if (this.parentSliderBar.isBackwards) {
			this.incrementValue(-1); // '-1' is the multiple, not the amount to increment by
			this.MyUpdateValue("keydown","down")		
		} else {
			this.incrementValue(1); // '1' is the multiple, not the amount to increment by
			this.MyUpdateValue("keydown","up")
		}
	}
	else if (this.KEYMAP[keyNum] == "leftArrowKey" || this.KEYMAP[keyNum] == "upArrowKey") {			
		if (this.parentSliderBar.handlesLen > 1) {
			this.multipleHandleMinMax()
		}
		if (this.parentSliderBar.isBackwards) {
			this.incrementValue(1); // '1' is the multiple, not the amount to increment by
			this.MyUpdateValue("keydown","up")			
		} else {
			this.incrementValue(-1); // '-1' is the multiple, not the amount to increment by
			this.MyUpdateValue("keydown","down")
		}
	}
	else if (this.KEYMAP[keyNum] == "enterKey" || this.KEYMAP[keyNum] == "tabKey") {
		this.MyUpdateValue("mouseend",null);
	}
}

SliderHandle_Class.prototype.KEYMAP = {
	
	 39:"rightArrowKey"
	,54:"rightArrowKey"
	,37:"leftArrowKey"
	,52:"leftArrowKey"
	,38:"upArrowKey"
	,104:"upArrowKey"
	,40:"downArrowKey"
	,98:"downArrowKey"
	,16:"shiftKey"
	, 9:"tabKey"
	,13:"enterKey"
	
}

// To make whichever handle we are moving the one on top

SliderHandle_Class.prototype._setZIndex = function(num) {
	this.el.style.zIndex = 10+num; //the 10 is arbitrary to give some wiggle z-index room above and below slider handle	
}


SliderHandle_Class.prototype.setMaxVal = function(val) {	
	this.maxVal = val;
}

SliderHandle_Class.prototype.getMaxVal = function() {	
	return this.maxVal;
}

SliderHandle_Class.prototype.setMaxPix = function(pos) {	
	this.maxPix = pos;
}

SliderHandle_Class.prototype.getMaxPix = function() {	
	return this.maxPix;
}

SliderHandle_Class.prototype.setMinVal = function(val) {
	this.minVal = val;
}

SliderHandle_Class.prototype.getMinVal = function() {
	return this.minVal;
}

SliderHandle_Class.prototype.setMinPix = function(pos) {
	this.minPix = pos;
}

SliderHandle_Class.prototype.getMinPix = function() {
	return this.minPix;
}

SliderHandle_Class.prototype.getPosition = function () {
	
	return this.currentPosition;

}

SliderHandle_Class.prototype.setPosition = function(pos) {

	this.currentPosition = pos; // note: pos is in the center of the handle	

}

SliderHandle_Class.prototype.finalDisplayFromValue = function(newVal) {

	var newVal = newVal != null ? newVal : this.currentValue;
	var newPos = Math.round(this.getPositionOfValue(newVal));

	if (newVal != this.currentValue) {

		if (newVal >= this.minVal && newVal <= this.maxVal) {
			this.setPosition(newPos);
			this.setValue(newVal);
			this._updateHandle()
		}
		else if (newVal < this.minVal) {
			if (this.parentSliderBar.isBackwards) {
				this.setPosition(this.maxPix)
			}
			else {
				this.setPosition(this.minPix)
			}
			this.setValue(this.minVal);
			this._updateHandle()
		}
		else if (newVal > this.maxVal) {
			if (this.parentSliderBar.isBackwards) {
				this.setPosition(this.minPix)
			} else {
				this.setPosition(this.maxPix)
			}
			this.setValue(this.maxVal);
			this._updateHandle()
		}
	}
}

SliderHandle_Class.prototype.finalDisplayFromPosition = function(newPos) {

	
	if (this.coordMap) { 
		var xCoord = Math.round(newPos);
		if(xCoord >= this.coordMap.length) { xCoord = this.coordMap.length-1; }
		if(xCoord < 0) { xCoord = 0; }
		var newPos = newPos != null ? this.coordMap[xCoord] : this.currentPosition;
		var newVal = this.valueMap[newPos];
		
		var leftSliderPos = 0 == this.whichHandle ? newPos : this.parentSliderBar.handles[0].getPosition();
		var rightSliderPos = 1 == this.whichHandle ? newPos : this.parentSliderBar.handles[1].getPosition();
		
		if (leftSliderPos >= rightSliderPos && this.oldPos) {
			newPos = this.oldPos;
		}
	} else {
		var newPos = newPos != null ? Math.round(newPos) : this.currentPosition;
		var newVal = this.getValueOfPosition(newPos);
	}
	
	if (newPos != this.currentPosition) {
		if (newPos >= this.minPix && newPos <= this.maxPix) {
			
			this.setPosition(newPos);
			this.setValue(newVal);
			this._updateHandle()
		}
		else if (newPos < this.minPix) {
			this.setPosition(this.minPix)
			if (this.parentSliderBar.isBackwards) {
				this.setValue(this.maxVal);
			} else {
				this.setValue(this.minVal);
			}
			this._updateHandle()
		}
		else if (newPos > this.maxPix) {
			this.setPosition(this.maxPix)
			if (this.parentSliderBar.isBackwards) {
				this.setValue(this.minVal);
			} else {
				this.setValue(this.maxVal);
			}
			this._updateHandle()
		}
		
		this.oldPos = newPos;
	}
	
}


SliderHandle_Class.prototype._updateHandle = function() {

	this.handleEdgePosition = (this.currentPosition - this.halfOfHandle + this.parentSliderBar.handleOffsetLow);

	if (this.parentSliderBar.isVertical) {
		this.el.style.top = this.handleEdgePosition + "px"; 	
	} else {
		this.el.style.left = this.handleEdgePosition + "px"; 	
	}
	
	
	if (this.parentSliderBar.handles.length > 1 && this.parentSliderBar.sliderBox) {

		var pos = this.coordMap 
			? this.coordMap[this.parentSliderBar.handles[0].getPosition()] 
			: this.parentSliderBar.handles[0].getPosition();
		
		var len = this.coordMap.length;
		
		
		var bigPos = this.parentSliderBar.handles[1].getPosition();
		var smallPos = this.parentSliderBar.handles[0].getPosition();
		if(bigPos >= len) { 
			bigPos = len-1; 
		}
		if(smallPos >= len) { 
			smallPos = len-1;
		}
		
		var size = this.coordMap 
			? this.coordMap[bigPos] - this.coordMap[smallPos]
			: bigPos - smallPos;
		
		if (this.parentSliderBar.isVertical) {
			this.parentSliderBar.sliderBox.style.top = pos + "px";
			this.parentSliderBar.sliderBox.style.height = size + "px";
		} else {
			this.parentSliderBar.sliderBox.style.left = pos + "px";
			this.parentSliderBar.sliderBox.style.width = size + "px";
		}
	}
}

SliderHandle_Class.prototype.getValue = function (skipConvert) {
	
	var ratio = skipConvert ? 1 : SecondaryCriteria.normalizeCurrency(this.criteria);
	return this.currentValue/ratio;

}

SliderHandle_Class.prototype.setValue = function (val) {
	
	this.currentValue = val;

}

SliderHandle_Class.prototype.incrementValue = function (multiple) {

	//multiple can be positive or negative.  
	this.finalDisplayFromValue(this.currentValue+(this.increment*multiple))
	
}

SliderHandle_Class.prototype.getValueOfPosition = function(pos) {
	
	if (this.parentSliderBar.isBackwards) {	
		return this.parentSliderBar.maxVal - (Math.round(pos) * this.parentSliderBar.valuePerPixel) ;
	} else {	
		return this.parentSliderBar.minVal + (Math.round(pos) * this.parentSliderBar.valuePerPixel) ;
	}
}

SliderHandle_Class.prototype.getPositionOfValue = function(val) {
	
	if (this.parentSliderBar.isBackwards) {
		return (this.parentSliderBar.maxVal - val) * this.parentSliderBar.pixelPerValue;
	} else {
		return (val - this.parentSliderBar.minVal) * this.parentSliderBar.pixelPerValue;
	}
}

SliderHandle_Class.prototype.findMouseOffset = function(pos) {

	this.mouseOffset = this.currentPosition - (Math.round(pos) - this.parentSliderBar.offsetFromEdge - this.parentSliderBar.handleOffsetLow);

}

SliderHandle_Class.prototype.multipleHandleMinMax = function() {

	if (this.parentSliderBar.handleOverlap != "none") {
	
		var overlapPix = this.parentSliderBar.handleOverlap == "handleEdge" ? this.handleLength : (this.parentSliderBar.handleOverlap == "nextPixel" ? 1 : !isNaN(Number(this.parentSliderBar.handleOverlap)) ? Number(this.parentSliderBar.handleOverlap) : 0);

		if (this.whichHandle > 0) { //For all handles except first one, where minimum is slider bar min

			this.setMinPix(this.parentSliderBar.handles[this.whichHandle-1].getPosition() + overlapPix)
			this.setMinVal(this.getValueOfPosition(this.getMinPix()));
			
		}
		if (this.whichHandle < this.parentSliderBar.handlesLen-1) { //For all handles except last one where max is slider bar max
		
			this.setMaxPix(this.parentSliderBar.handles[this.whichHandle+1].getPosition() - overlapPix)
			this.setMaxVal(this.getValueOfPosition(this.getMaxPix()));
		}
		
	}

}

SliderHandle_Class.prototype.keyPressMinMax = function(dir) {

	if (this.parentSliderBar.handleOverlap != "all") {

		var overlapPix = this.parentSliderBar.handleOverlap == "handleEdge" ? this.handleLength : (this.parentSliderBar.handleOverlap == "nextPixel" ? 1 : !isNaN(Number(this.parentSliderBar.handleOverlap)) ? Number(this.parentSliderBar.handleOverlap) : 0);		
		
		if (dir == "right") {
			if (this.parentSliderBar.handles[this.whichHandle+1]) {
				this.parentSliderBar.handles[this.whichHandle+1].setMinPix(this.getPosition() + overlapPix)
			}
		}
		else if (dir == "left") {
			if (this.parentSliderBar.handles[this.whichHandle-1]) {
				this.parentSliderBar.handles[this.whichHandle-1].setMaxPix(this.getPosition() - overlapPix)
			}
		}
			
	}
	
}

/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/screener/CriteriaPopup.js
*/

/**
 * @classDescription CriteriaPopup
 * @constructor
 */
var CriteriaPopup = function(screenerCriteria) {
	this.screenerCriteria = screenerCriteria;

	CriteriaPopup.Super(this);
}


/**
 * @method Extend
 * Extend the 'Popup' class, which is defined in /ft/resources/client/Popup.js.
 */
CriteriaPopup.Extend(Popup);


/**
 * @method attachEvents
 * Attach events to passed elements
 */
CriteriaPopup.prototype.attachEvents = function(currentElement) {
	if (currentElement) {
		this.getEventManagerForCriteriaPopup().add(
			{
				 context:	this
				,element:	currentElement
				,handler:	currentElement.handler || function() { console.log('Event handler is missing'); }
				,type:		currentElement.type || function() { console.log('Event type is missing'); }
			}
		);
	}

}


/**
 * @method convertArrayToObject
 */
CriteriaPopup.prototype.convertArrayToObject = function(arr, key) {
	var obj = {};

	for (var i = 0; i < arr.length; i++) {
		obj[arr[i][key]] = arr[i];
	}

	return obj;
}


/**
 * @method convertObjectToArray
 */
CriteriaPopup.prototype.convertObjectToArray = function(obj) {
	var arr = [];

	for (var i in obj) {
		arr.push(obj[i]);
	}

	return arr;
}


/**
 * @method getCriteria
 */
CriteriaPopup.prototype.getCriteria = function() {
	return null;
}


/**
 * @method setCriteria
 */
CriteriaPopup.prototype.setCriteria = function(criteria, checkboxToUncheck) {
	var criteria			= criteria;
	var criteriaObject		= this.convertArrayToObject(criteria, 'field');
	var checkboxToUncheck	= checkboxToUncheck || false;

	if (this.getFrame().id) {
		if (checkboxToUncheck) {
			var inputElements = Element.parseSelector('INPUT[field="' + checkboxToUncheck + '"]', this._containerForListOfGroups);

			if (inputElements) {
				for (var i = 0; i < inputElements.length; i++) {
					inputElements[i].checked = false;
				}
			}
		}
	}

	this.getCriteria = function() {
		return criteria;
	}
	
	this.getCriteriaObject = function() {
		return criteriaObject;
	}
}


/**
 * @method showThePopup
 */
CriteriaPopup.prototype.showThePopup = function() {
	var currentId = this.getFrame().id || false;

	if (currentId && Element.hasClass(this.getFrame(), 'wsodHidden')) {
		var checkedCriteriaObject = this.convertArrayToObject(this.getCriteria(), 'field');

		for (var i = 0; i < this._possibleCriteria.length; i++) {
			if (checkedCriteriaObject[this._possibleCriteria[i].getAttribute('field')]) {
				this._possibleCriteria[i].checked = 'checked';
			}
			else {
				this._possibleCriteria[i].checked = false;
			}
		}

		// Re-attach the events
		this.attachEvents(this.duplicateCheckboxes);
		this.attachEvents(this._buttonForCancel);
		this.attachEvents(this._buttonForAddSelectedCriteria);

		Element.removeClass(this.getFrame(), 'wsodHidden');
		Element.setVisibility(this.getFrame(), 'visible');
	}
	else {
		this.getFrame().id = 'screenerCriteriaPopup';

		this.draw();
	}
}


/**
 * @method addSelectedCriteria
 */
CriteriaPopup.prototype.addSelectedCriteria = function(e, el) {
	var checkedCriteria = [];
	var criteriaObject = this.getCriteriaObject();
	
	for (var i = 0, field; i < this._possibleCriteria.length; i++) {
		field = this._possibleCriteria[i].getAttribute('field');
		
		
		if (this._possibleCriteria[i].checked) {
			if (!criteriaObject[field]) {
				
				criteriaObject[field] = { field: field };
				this.screenerCriteria.getSecondaryCriteria(criteriaObject[field]);
			}
		} else {
			if (criteriaObject[field]) {
				delete criteriaObject[field];
				this.screenerCriteria.removeSecondaryCriteria(field);
			}
		}
	}

	this.setCriteria(this.convertObjectToArray(criteriaObject));

	this.screenerCriteria.getPreScreen(true);

	this.closeThePopup(e, el);
}


/**
 * @method closeThePopup
 */
CriteriaPopup.prototype.closeThePopup = function(e, el) {
	this.getCloseEvent().addElement(Element.getParent(el, 'div'));


	this.getEventManagerForCriteriaPopup().removeAll();

}


/**
 * @method getEventManagerForCriteriaPopup
 * This method removes the events defined in the CriteriaPopup class, but will NOT remove the methods defined in the Popup class.
 * (It has been locally named getEventManagerForCriteriaPopup() to avoid any conflicts with Popup's getEventManager().)
 */
CriteriaPopup.prototype.getEventManagerForCriteriaPopup = function() {
	var em = new EventManager();

	this.getEventManagerForCriteriaPopup = function() {
		return em;
	};

	return this.getEventManagerForCriteriaPopup();
};


/**
 * @method getContentBuffer
 */
CriteriaPopup.prototype.getContentBuffer = function() {
	var contentBuffer = new ContentBuffer();

	this.getContentBuffer = function() {
		return contentBuffer;
	}

	return this.getContentBuffer();
}


/**
 * @method getSerializer
 */
CriteriaPopup.prototype.getSerializer = function() {
	var serializer = new Serializer();
		serializer.allowEncoding(false);

	this.getSerializer = function() {
		return serializer;
	}

	return this.getSerializer();
}


/**
 * @method loadContentBuffer
 */
CriteriaPopup.prototype.loadContentBuffer = function(data) {
	this.getContentBuffer().abortRequests();  // If the user happens to click several buttons, only load the most recent request

	this.getContentBuffer().load(
		{
		contentType:	'text/javascript',
		context:		this,
		url:			'/ft/screener/data/CriteriaPopup.asp',
		method:			'post',
		data:			{ serializedParams: this.getSerializer().serialize(data) },
		onload:			this.onBufferLoad,
		onerror:		this.onBufferError,
		preventEval:	true,
		debug:			true
		}
	);
}


/**
 * @method onBufferLoad
 */
CriteriaPopup.prototype.onBufferLoad = function(cb) {
	var results = this.getSerializer().deserialize(cb.getResult());

	this._mainContent.innerHTML = 'Under construction.';
}


/**
 * @method onBufferError
 */
CriteriaPopup.prototype.onBufferError = function(cb) {
	var results = this.getSerializer().deserialize(cb.getResult());

	this._mainContent.innerHTML = 'Sorry, this feature is not currently available.';
}


/**
 * @method drawButton
 */
CriteriaPopup.prototype.drawButton = function(inputs) {
	var inputs						= inputs || {};

	// Set the button's attribute(s) and InnerHTML
	var buttonText					= inputs.buttonText				|| '';
	var classForInnerButton			= inputs.classForInnerButton	|| false;
	var classForOuterButton			= (inputs.classForOuterButton) ? 'basicButton ' + inputs.classForOuterButton : 'basicButton';
	var idAttribute					= inputs.idAttribute			|| false;

	// Create the button
	var outerButton					= Element.create('div', { className:classForOuterButton }, null);
	var button						= Element.create('div', {}, buttonText, outerButton);

	if (classForInnerButton) {
		button.className			= classForInnerButton;
	}

	if (idAttribute) {
		outerButton.setAttribute('id', idAttribute);
	}

	return outerButton;
}


/**
 * @method drawCriteria
 * Draw the list of criteria.
 */
CriteriaPopup.prototype.drawCriteria = function() {
	checkedCriteria	= [];

	var defaultCriteriaObject = this.convertArrayToObject(this.getCriteria(), 'field');

	var results = this.SCREENER_CRITERIA;

	this._containerForListOfGroups.innerHTML	= '';

	if (results) {
		this._listOfGroups						= Element.create('table', { id:'listOfGroups' }, null, this._containerForListOfGroups);
		var containerForCurrentGroup;
		var currentGroupName					= '';
		var previousGroupName					= '';
		var containerForCurrentGroupName;
		var containerForCurrentListOfCriteria;
		var currentListOfCriteria;
		var currentCheckbox;
		
		var tbody = Element.create("tbody",{},null, this._listOfGroups);
		
		var groupedCriteria = {};
		var orderedCriteria = [];
		var currentResult;

		for (var i in results) {
			currentResult = results[i];

			var group = currentResult.group;
			if (!group) { continue; }
			if (!groupedCriteria[group]) {
				groupedCriteria[group] = [];

				orderedCriteria.push(group);
			}
			groupedCriteria[group].push(currentResult);

			currentResult.Field = i;

			// If a criteria is available in a second group; this is relatively uncommon
			var group2 = currentResult.group2;
			if (!group2) { continue; }
			if (!groupedCriteria[group2]) {
				groupedCriteria[group2] = [];

				orderedCriteria.push(group2);
			}
			groupedCriteria[group2].push(currentResult);

			if (group && group2) {
				currentResult.multipleGroups = true;
			}
		}
		
		var currentGroup, criteriaInGroup, thisCriteria, thisFullName;
		for(var i=0; i<orderedCriteria.length; i++) {
			
			currentGroup = orderedCriteria[i];
			criteriaInGroup = groupedCriteria[currentGroup];
			
			containerForCurrentGroup		= Element.create('tr', { className:'containerForCurrentGroup' }, null, tbody);
			containerForCurrentGroupName	= Element.create('td', { className:'groupNameToDisplay' }, currentGroup.replace(/\s/g, '<br />'), containerForCurrentGroup);
			containerForCurrentList			= Element.create('td', { className:'containerForCurrentList' }, null, containerForCurrentGroup);
			currentList						= Element.create('ul', {}, null, containerForCurrentList);
			
			if(i == 0) {
				Element.addClass(containerForCurrentGroup, 'defaultCriteriaGroup');
			}
			
			
			for (var j=0; j<criteriaInGroup.length; j++) {
				thisCriteria = criteriaInGroup[j];
				thisFullName = thisCriteria.full_name.replace(/\<br \/\>/g,' ');

				currentCheckbox = Element.create('input', { 'className':'criteriaCheckbox', 'type':'checkbox', 'field':thisCriteria.Field }, null);

				if (thisCriteria.multipleGroups) {
					Element.setAttribute(currentCheckbox, 'multipleGroups', 'true');
				}

				Element.create('li', {}, [
						Element.create('label', {}, [
					 	 	 currentCheckbox
					 		,Element.create('span', {}, thisFullName)
					 	])
					 ]
					,currentList
				);
	
				if (defaultCriteriaObject[thisCriteria.Field]) {
					currentCheckbox.checked = 'checked';  // true
					currentCheckbox.defaultChecked = 'true';
					checkedCriteria.push(defaultCriteriaObject[thisCriteria.Field]);
				}
				
			}
			
		}
		
	}
	else {
	}
	

	this._possibleCriteria	= Element.parseSelector('input.criteriaCheckbox', tbody);
}


/**
 * @method draw
 * Draw the poup.
 */
CriteriaPopup.prototype.draw = function() {
	if (this.isVisible()) {
		return;
	}

	this.clearContent();

	// Header portion of the popup window
	this.setTitleText('<div id="headerForGlobalEquityScreener">Global Equity Screener</div><div>Add Screener Criteria</div>');
	Element.addClass(this.getTitle(), 'addCriteriaHeader');

	this._containerForListOfGroups = Element.create('div', { id:'containerForListOfGroups' }, null);
	this.drawCriteria();

	this.duplicateCheckboxes = Element.parseSelector('INPUT[multipleGroups="true"]', this._listOfGroups);
		this.duplicateCheckboxes.handler = function(ev, el) {
			var currentCheckbox;
			var currentField = el.getAttribute('field');

			for (var i = 0; i < this.duplicateCheckboxes.length; i++) {
				currentCheckbox = this.duplicateCheckboxes[i];

				if (currentCheckbox == el) {
					continue;
				}

				if (el.checked) {
					if ((currentCheckbox != el) && (currentField == currentCheckbox.getAttribute('field'))) {
						currentCheckbox.checked = true;
						break;
					}
				}
				else {
					if ((currentCheckbox != el) && (currentField == currentCheckbox.getAttribute('field'))) {
						currentCheckbox.checked = false;
						break;
					}
				}
			}
		};
		this.duplicateCheckboxes.type = 'click';
	this.attachEvents(this.duplicateCheckboxes);

	this._buttonForCancel				= this.drawButton({ buttonText: 'Cancel' });
		this._buttonForCancel.handler	= this.closeThePopup;
		this._buttonForCancel.type		= 'click';
	this.attachEvents(this._buttonForCancel);

	this._buttonForAddSelectedCriteria				= this.drawButton({ buttonText: 'Add Selected Criteria', classForOuterButton: 'last' });
		this._buttonForAddSelectedCriteria.handler	= this.addSelectedCriteria;
		this._buttonForAddSelectedCriteria.type		= 'click';
	this.attachEvents(this._buttonForAddSelectedCriteria);

	var popupFooterButtons = Element.create('div', { className:'fright' }, [ this._buttonForCancel, this._buttonForAddSelectedCriteria ]);

	// Main content of the popup window
	this._mainContent = Element.create('div', { id:'mainContent' }, [
		 Element.create('div', { id:'instructionsForAddingCriteria' }, 'Tick the criteria you wish to add to your equity screen.')
		,this._containerForListOfGroups
		,Element.create('div', { id:'popupFooter' }, popupFooterButtons)
		], this.getContent());
		

	CriteriaPopup.Super(this, 'draw');
}

/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/screener/SaveCriteriaPopup.js
*/

/**
 * @classDescription SaveCriteriaPopup
 * @constructor
 */
var SaveCriteriaPopup = function(screenerName) {
	SaveCriteriaPopup.Super(this);
	this.screenerName = screenerName;
}


/**
 * @method Extend
 * Extend the 'Popup' class, which is defined in /ft/resources/client/Popup.js
 */
SaveCriteriaPopup.Extend(Popup);


/**
 * @method attachEvents
 * Attach events to passed elements
 */
SaveCriteriaPopup.prototype.attachEvents = function(currentElement) {
	if (currentElement) {
		this.getEventManagerForSaveCriteriaPopup().add(
			{
				 context:	this
				,element:	currentElement
				,handler:	currentElement.handler || function() { console.log('Event handler is missing'); }
				,type:		currentElement.type || function() { console.log('Event type is missing'); }
			}
		);
	}

	// console.log(this.getEventManagerForSaveCriteriaPopup());
}


/**
 * @method convertArrayToObject
 */
SaveCriteriaPopup.prototype.convertArrayToObject = function(arr, key) {
	var obj = {};

	for (var i = 0; i < arr.length; i++) {
		obj[arr[i][key]] = arr[i];
	}

	return obj;
}


/**
 * @method getEventManagerForSaveCriteriaPopup
 * This method removes the events defined in the SaveCriteriaPopup class, but will NOT remove the methods defined in the Popup class.
 * (It has been locally named getEventManagerForSaveCriteriaPopup() to avoid any conflicts with Popup's getEventManager().)
 */
SaveCriteriaPopup.prototype.getEventManagerForSaveCriteriaPopup = function() {
	var em = new EventManager();

	this.getEventManagerForSaveCriteriaPopup = function() {
		return em;
	}

	return this.getEventManagerForSaveCriteriaPopup();
}


/**
 * @method showThePopup
 */
SaveCriteriaPopup.prototype.showThePopup = function() {
	var currentId = this.getFrame().id || false;
		// console.log(currentId);
		// console.log(this.getFrame());

	if (currentId) {
		if (this.isVisible()) {
			// console.log('Already visible');
		}
		else {
			if (Element.hasClass(this.getFrame(), 'wsodHidden')) {
				// console.log('REMOVING the hidden class and resetting the visibility');

				// Re-attach the events
				// this.attachEvents(this._buttonForCancel);
				// this.attachEvents(this._buttonForSave);

				this.clearContent();
				this.getDefaultView();

				Element.removeClass(this.getFrame(), 'wsodHidden');
				Element.setVisibility(this.getFrame(), 'visible');
			}
		}
	}
	else {
		// console.log('DRAWING a new popup');
		this.getFrame().id = 'saveCriteriaPopup';

		this.draw();

		var sizeOfPopup = Element.getSize(this.getFrame());
		Element.setSize(Element.parseSelector('div.popupInner', this.getFrame(), 'first'), sizeOfPopup.width, sizeOfPopup.height);
	}
}


/**
 * @method closeThePopup
 */
SaveCriteriaPopup.prototype.closeThePopup = function(e, el) {
	this.getCloseEvent().addElement(Element.getParent(el, 'div'));

	// console.log('BEFORE REMOVING ALL EVENTS (Note: Firebug hides the details about the Events, if/when .removeAll() is called.)');
	// console.log(this.getEventManagerForSaveCriteriaPopup());

	this.getEventManagerForSaveCriteriaPopup().removeAll();

	// console.log('AFTER REMOVING ALL EVENTS');
	// console.log(this.getEventManagerForSaveCriteriaPopup());
}


/**
 * @method getCriteria
 */
SaveCriteriaPopup.prototype.getCriteria = function() {
	return null;
}


/**
 * @method setCriteria
 */
SaveCriteriaPopup.prototype.setCriteria = function(criteria) {
	var criteria			= criteria;
	var criteriaObject		= this.convertArrayToObject(criteria, 'field');

	this.getCriteria = function() {
		return criteria;
	}

	this.getCriteriaObject = function() {
		return criteriaObject;
	}
}


/**
 * @method saveNamedCriteria
 */
SaveCriteriaPopup.prototype.saveNamedCriteria = function(e, el) {
	var proposedName = Element.get('savedCriteriaName').value || false;

	if (!proposedName || !proposedName.length) {
		alert('Please enter a name.');
		return false;
	}

	var data = {
		 serializedAction:		this.getSerializer().serialize('saveCriteria')
		,serializedName:		this.getSerializer().serialize(proposedName)
		,serializedCriteria:	this.getSerializer().serialize(this.getCriteria())
		,forceOverwrite:		this.getSerializer().serialize((proposedName == this.screenerName) ? true : false)
	};

	this.loadContentBuffer(data);
}


/**
 * @method getContentBuffer
 */
SaveCriteriaPopup.prototype.getContentBuffer = function() {
	var contentBuffer = new ContentBuffer();

	this.getContentBuffer = function() {
		return contentBuffer;
	}

	return this.getContentBuffer();
}


/**
 * @method getSerializer
 */
SaveCriteriaPopup.prototype.getSerializer = function() {
	var serializer = new Serializer();
		serializer.allowEncoding(true);

	this.getSerializer = function() {
		return serializer;
	}

	return this.getSerializer();
}


/**
 * @method loadContentBuffer
 */
SaveCriteriaPopup.prototype.loadContentBuffer = function(data) {
	this.getContentBuffer().abortRequests();  // If the user happens to click several buttons, only load the most recent request

	this.getContentBuffer().load(
		{
			 contentType:	'text/javascript'
			,context:		this
			,url:			'/ft/screener/data/SaveCriteriaPopup.asp'
			,method:		'post'
			,data:			data
			,onload:		this.onBufferLoad
			,onerror:		this.onBufferError
			,preventEval:	true
			,debug:			true
		}
	);
}


/**
 * @method onBufferLoad
 */
SaveCriteriaPopup.prototype.onBufferLoad = function(cb) {
	var results = this.getSerializer().deserialize(cb.getResult());
		// console.log(results);
	var text = "";

	if (results) {
		if (results.limitReached) {
			// Header portion of the popup window
			this.setTitleText('<div>WE\'RE SORRY</div>');

			text = 'Only 25 screens can be saved at a time.  Remove some of your existing saved screens and try again.';
		}
		else if (results.labelCollision) {
			// Header portion of the popup window
			this.setTitleText('<div>WE\'RE SORRY</div>');

			text = 'That name is already used.  Please try again.';
		}
		else {
			Element.removeChildNodes(this._instructionsAndNameContainer);
			text = "Your criteria has been saved to <a href='savedScreens.asp'>Your Saved Screens</a>. Please click OK to close.";
		}

		this._buttonForOk				= this.drawButton({ buttonText: 'OK' });
			this._buttonForOk.handler	= this.closeThePopup;
			this._buttonForOk.type		= 'click';
		this.attachEvents(this._buttonForOk);

		// Main content of the popup window
		this._mainContent.innerHTML	= '';
		this._mainContent			= Element.create('div', { id:'mainContent' }, [
			 	 text
				,Element.create('div', { id:'popupFooter' }, Element.create('div', { className:'fright' }, this._buttonForOk))
			], this.getContent());
	}
}


/**
 * @method onBufferError
 */
SaveCriteriaPopup.prototype.onBufferError = function(cb) {
	var results = this.getSerializer().deserialize(cb.getResult());
		// console.log(results);

	this._instructionsAndNameContainer.innerHTML = 'Sorry, this feature is not currently available.';
}


/**
 * @method drawButton
 */
SaveCriteriaPopup.prototype.drawButton = function(inputs) {
	var inputs						= inputs || {};

	// Set the button's attribute(s) and InnerHTML
	var buttonText					= inputs.buttonText				|| '';
	var classForInnerButton			= inputs.classForInnerButton	|| false;
	var classForOuterButton			= (inputs.classForOuterButton) ? 'basicButton ' + inputs.classForOuterButton : 'basicButton';
	var idAttribute					= inputs.idAttribute			|| false;

	// Create the button
	var outerButton					= Element.create('div', { className:classForOuterButton }, null);
	var button						= Element.create('div', {}, buttonText, outerButton);

	if (classForInnerButton) {
		button.className			= classForInnerButton;
	}

	if (idAttribute) {
		outerButton.setAttribute('id', idAttribute);
	}

	return outerButton;
}


/**
 * @method getDefaultView
 * Draw the default text
 */
SaveCriteriaPopup.prototype.getDefaultView = function() {
		// Header portion of the popup window
		this.setTitleText('<div>SAVE SCREENER CRITERIA</div>');

		this._instructionsAndNameContainer = Element.create('div', {}, [
				 Element.create('div', {}, "Please name this set of saved criteria, for access later in the 'Your Saved Screens' tab.")
				,Element.create('div', { id:'savedCriteriaNameContainer' }, '<input id="savedCriteriaName" type="text" value="' + this.screenerName + '" />' )	
			]
		);

		this._buttonForCancel				= this.drawButton({ buttonText: 'Cancel' });
			this._buttonForCancel.handler	= this.closeThePopup;
			this._buttonForCancel.type		= 'click';
		this.attachEvents(this._buttonForCancel);

		this._buttonForSave					= this.drawButton({ buttonText: 'Save', classForOuterButton: 'last' });
			this._buttonForSave.handler		= this.saveNamedCriteria;
			this._buttonForSave.type		= 'click';
		this.attachEvents(this._buttonForSave);

		var popupFooterButtons = Element.create('div', { className:'fright' }, [ this._buttonForCancel, this._buttonForSave ]);

		// Main content of the popup window
		this._mainContent = Element.create('div', { id:'mainContent' }, [
			 	 this._instructionsAndNameContainer
				,Element.create('div', { id:'popupFooter' }, popupFooterButtons)
			], this.getContent());
}


/**
 * @method setDefaultView
 * Draw the default text
 */
SaveCriteriaPopup.prototype.setDefaultView = function() {
		// Header portion of the popup window
		this.setTitleText('<div>LOG IN TO FINANCIAL TIMES</div>');

		this._instructionsAndNameContainer = Element.create('div', {}, [
				  Element.create('div', {}, 'Please log in to save your screener criteria.  If you are not currently registered for this site, these are some of the benefits of registration:')
				 ,Element.create('ul', {}, [
				 		 Element.create('li', {}, ' - More articles per 30 days')
				 		,Element.create('li', {}, ' - Price and portfolio email alerts')
				 		,Element.create('li', {}, ' - Portfolio tool')
				 		,Element.create('li', {}, ' - News by email')
				 	]
				 )
			]
		);

		this._buttonForCancel				= this.drawButton({ buttonText: 'Cancel' });
			this._buttonForCancel.handler	= this.closeThePopup;
			this._buttonForCancel.type		= 'click';
		this.attachEvents(this._buttonForCancel);

		this._buttonForRegister				= this.drawButton({ buttonText: 'Register &amp; Log In', classForOuterButton: 'last' });
			this._buttonForRegister.handler	= this.register;
			this._buttonForRegister.type	= 'click';
		this.attachEvents(this._buttonForRegister);

		var popupFooterButtons = Element.create('div', { className:'fright' }, [ this._buttonForCancel, this._buttonForRegister ]);

		// Main content of the popup window
		this._mainContent = Element.create('div', { id:'mainContent' }, [
			 	 this._instructionsAndNameContainer
				,Element.create('div', { id:'popupFooter' }, popupFooterButtons)
			], this.getContent());
}


/**
 * @method register
 * Register for / Log into ft.com
 */
SaveCriteriaPopup.prototype.register = function() {
	// console.log(this.REGISTRATION_URL);
	location.href = this.REGISTRATION_URL;
}


/**
 * @method draw
 * Draw the popup
 */
SaveCriteriaPopup.prototype.draw = function() {
	this.clearContent();

	this.getDefaultView();

	SaveCriteriaPopup.Super(this, 'draw');
}

/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/screener/Primary.Criteria.js
*/
var PrimaryCriteria = function(field, values) {
	this.setField(field);
	this.setValues(values);
	this.setView(this.getValues());
}

PrimaryCriteria.prototype.CODE_POPULAR = "POP";
PrimaryCriteria.prototype.NULL_VALUE = -32768;
PrimaryCriteria.prototype.OPERATOR = "LIKE";

PrimaryCriteria.prototype.CRITERIA_ATTRIBUTES = {
	"CountryCode": {
		parentCode: "regionCode",
		parentClass: "regionalFocus"
	},
	"IndustryCode": {
		parentCode: "sectorCode",
		parentClass: "sectorsAndIndustries"
	}
}

PrimaryCriteria.prototype.getField = function() { return ""; }
PrimaryCriteria.prototype.setField = function(field) {
	this.getField = function() {
		return field;
	}
}

PrimaryCriteria.prototype.getValues = function() { return ""; }
PrimaryCriteria.prototype.setValues = function(values) {
	var settings = [];
	
	if (values && values.length) {
		values = values[0].split("|")
		
		for (var i = 0, params, operator, arguments; i < values.length; i++) {
			params = values[i].split(":");
			
			if (params.length && params.length > 1) {
				settings = params[1].split(",");
			}
		}
	}

	this.getValues = function() {
		return settings;
	}
	
	this.setValues = function(values) {
		settings = values;
	}
}

PrimaryCriteria.prototype.isAllView = function() { return false; }
PrimaryCriteria.prototype.setView = function(values) {
	var isAllView = values && values.length ? false : true;
	
	this.isAllView = function(view) {
		if (undefined !== view) { isAllView = view; }
		
		return isAllView;
	}
}

PrimaryCriteria.prototype.getCriteriaObject = function() { return {}; }
PrimaryCriteria.prototype.setCriteriaObject = function(obj) {
	var criteriaObj = obj;
	var values = this.getValues();
	
	this.getCriteriaObject = function() {
		return criteriaObj;
	}
}

PrimaryCriteria.prototype.getChildObject = function() {
	var child = {};
	
	this.getChildObject = function() {
		return child;
	}
	
	return this.getChildObject();
}

PrimaryCriteria.prototype.getParentObject = function() {
	var parent = {};
	
	this.getParentObject = function() {
		return parent;
	}
	
	return this.getParentObject();
}

PrimaryCriteria.prototype.addChild = function(code) {
	var children = this.getChildObject();
	var child = this.getCriteriaObject()[code];
	
	if (!children[code]) {
		children[code] = true;
		this.addParent(child[this.CRITERIA_ATTRIBUTES[this.getField()].parentCode], child.isPopular);
	}
}

PrimaryCriteria.prototype.removeChild = function(code) {
	var children = this.getChildObject();
	var child = this.getCriteriaObject()[code];
	
	if (children[code]) {
		delete children[code];
		this.removeParent(child[this.CRITERIA_ATTRIBUTES[this.getField()].parentCode], child.isPopular);
	}
}

PrimaryCriteria.prototype.toggleChild = function(code) {
	var children = this.getChildObject();

	if (children[code]) {
		this.removeChild(code);
	} else {
		this.addChild(code);
	}
}

PrimaryCriteria.prototype.addParent = function(parentCode, isPopular) {
	var parents = this.getParentObject();
	
	parents[parentCode] = undefined != parents[parentCode] ? parents[parentCode]+1 : 1;
	if (isPopular) { parents[this.CODE_POPULAR] = undefined != parents[this.CODE_POPULAR] ? parents[this.CODE_POPULAR]+1 : 1; }
	
	this.renderActiveParents();
}

PrimaryCriteria.prototype.removeParent = function(parentCode, isPopular) {
	var parents = this.getParentObject();
	
	if (parents[parentCode] == 1) {
		delete parents[parentCode];
	} else {
		parents[parentCode] -= 1;
	}
	
	if (isPopular) {
		if (parents[this.CODE_POPULAR] == 1) {
			delete parents[this.CODE_POPULAR];
		} else {
			parents[this.CODE_POPULAR] -= 1;
		}
	}
	
	this.renderActiveParents();
}

PrimaryCriteria.prototype.renderActiveParents = function() {
	var parents = this.getParentObject();
	var optionsContainer = this.getOptionsContainer();
	var childLink;
	
	Element.removeClass(Element.parseSelector("ul li a", optionsContainer), "hasActiveCountries");
	if (!this.isAllView()) {
		for (var i in parents) {
			childLink = Element.parseSelector("ul li a["+this.CRITERIA_ATTRIBUTES[this.getField()].parentCode+"='" + i + "']", optionsContainer, "first");
			
			if (childLink) { Element.addClass(childLink, "hasActiveCountries"); }
		}
	}
}

PrimaryCriteria.prototype.getOptionsContainer = function() {
	var optionsContainer = Element.parseSelector("div."+this.CRITERIA_ATTRIBUTES[this.getField()].parentClass, "wsod", "first");
	
	this.getOptionsContainer = function() {
		return optionsContainer;
	}
	
	return this.getOptionsContainer();
}

PrimaryCriteria.prototype.exportCriteria = function() {
	var children = this.getChildObject();
	
	var criteria = {field: this.getField()};
	
	var values = [], selections = [];
	for (var i in children) {
		selections.push(i);
	}
	
	if (!selections.length && !this.isAllView()) {
		selections.push(this.NULL_VALUE);
	}
	
	if (selections.length && !this.isAllView()) {
		values = [[this.OPERATOR].concat([selections.join(",")]).join(":")];
		criteria.values = values;
	}
	
	return criteria;
}
/*
FILE CONCAT ADD FILE
PATH: /ft/resources/client/screener/Secondary.Criteria.js
*/
var SecondaryCriteria = function(screenerCriteria, field, values) {
	this.screenerCriteria = screenerCriteria;
	
	this.setField(field);
	this.setType(field);
	this.setValues(values);
	this.setDynamicLabels(field)
	
	
	this.setNormalization(field)
}


SecondaryCriteria.prototype.setDynamicLabels = function(field) {
	var criteria = this.SCREENER_CRITERIA[field];
	var labels = criteria.dynamic_labels || {};
	
	this.dynamic_labels = labels;
}

SecondaryCriteria.prototype.getNormalization = function() { return true; }
SecondaryCriteria.prototype.setNormalization = function(field) {
	var criteria = this.SCREENER_CRITERIA[field];
	var normalize = criteria.normalize_to_currency;
	
	this.getNormalization = function() {
		return normalize;
	}
}



SecondaryCriteria.normalizeCurrency = function(context) { 

	//make sure to check if this criteria gets normalized
	if(context && !context.getNormalization()) {
		return 1;
	}
	return SecondaryCriteria.conversionRate(); 
}

SecondaryCriteria.conversionRate = function() { return 1; }

SecondaryCriteria.prototype.convertSliderData = function() {
	var controls = this.getCriteriaControls();
	
	var minValueEl = Element.parseSelector("div.minValue",controls,"first");
	var maxValueEl = Element.parseSelector("div.maxValue",controls,"first");
	var lowValueEl = Element.parseSelector("div.highLowContainer div.lowValue",controls,"first");
	var highValueEl = Element.parseSelector("div.highLowContainer div.highValue",controls,"first");
	
	var self = this;
	
	(this.convertSliderData = function() {
		
		if(!self.getSliderMinValue) { return; }
		
		var minValue = self.getSlider().oData.minVal;
		var maxValue = self.getSlider().oData.maxVal;
		
		var rate = SecondaryCriteria.normalizeCurrency(self);
		
		minValue /= rate;
		maxValue /= rate;
		
//		console.log("Converting", self.formatValue(minValue), self.formatValue(maxValue));
		
		Element.setHTML(minValueEl,self.formatValue(minValue))
		Element.setHTML(maxValueEl,self.formatValue(maxValue))
		
		self.fireHandleEvent(true)
		
	})()
}

SecondaryCriteria.prototype.SLIDER_SIZE = 204;
SecondaryCriteria.prototype.NON_SLIDER_FIELDS = {
	"ConsensusRecommendation": [
		{display: "Buy", value: "BUY", css: "buy"},
		{display: "Out perform", value: "OUTPERFORM", css: "perform"},
		{display: "Hold", value: "HOLD", css: "hold"},
		{display: "Under perform", value: "UNDERPERFORM", css: "perform"},
		{display: "Sell", value: "SELL", css: "sell"},
		{display: "No rating", value: "NORATING", css: "norating"}
	]
}

SecondaryCriteria.prototype.getField = function() { return null; }
SecondaryCriteria.prototype.setField = function(field) {
	this.getField = function() {
		return field;
	}
	
	return this.getField();
}

SecondaryCriteria.prototype.isSliderItem = function(field) { return false; }
SecondaryCriteria.prototype.setType = function(field) {
	var isSliderItem = this.NON_SLIDER_FIELDS[field] ? false : true;
	
	this.isSliderItem = function() {
		return isSliderItem;
	}
}

SecondaryCriteria.prototype.getValues = function() { return null; }
SecondaryCriteria.prototype.setValues = function(values) {
	var settings = {};
	
	if (values && values.length) {
		values = values[0].split("|")
		
		for (var i = 0, params, operator, arguments; i < values.length; i++) {
			params = values[i].split(":");
			operator = params[0];
			
			arguments = "LIKE" == operator ? params[1] : Number(params[1]);
			
			settings[operator] = arguments;
		}
	}
	
	this.setValues = function(values) {
		settings = values;
	}

	this.getValues = function() {
		return settings;
	}
	
	return this.getValues();
}

SecondaryCriteria.prototype.draw = function() {
	var content = this.getContent();
	
	this.getEventManager().add(this.getRemoveLink(), "click", this.remove, this);
	
	if (this.isSliderItem()) {
		this.getEventManager().add(this.getSpecificValues(), "click", this.toggleCriteriaEntry, this);
		this.getEventManager().add(this.getBackToChart(), "click", this.toggleCriteriaEntry, this);
		this.getEventManager().add(this.getSpecificValues(), "mouseover", this.showSpecificValueLink, this);
		this.getEventManager().add(this.getSpecificValues(), "mouseout", this.hideSpecificValueLink, this);
		this.getEventManager().add(this.getInputLow(), "keyup", this.modifySpecificValueTimeout, this);
		this.getEventManager().add(this.getInputHigh(), "keyup", this.modifySpecificValueTimeout, this);
	} else {
		this.getEventManager().add(this.getButtonControls(), "click", this.toggleButtonControl, this);
	}
	
	Element.removeClass(content, "hide");
	
	var criteriaSliderSize = Element.getSize(this.getCriteriaControls());
 	var criteriaInfoSize = Element.getSize(this.getCriteriaInfo());
	var preScreenCumulativeSize = Element.getSize(this.getPreScreenCumulative());
	var preScreenIndividualSize = Element.getSize(this.getPreScreenIndividual());
	
	Element.setStyle(this.getCriteriaInfo(), "margin-top: "+Math.floor((criteriaSliderSize.height - criteriaInfoSize.height) / 2)+"px;");
	Element.setStyle(this.getPreScreenCumulative(), "margin-top: "+Math.floor((criteriaSliderSize.height - preScreenCumulativeSize.height) / 2)+"px;");
	Element.setStyle(this.getPreScreenIndividual(), "margin-top: "+Math.floor((criteriaSliderSize.height - preScreenIndividualSize.height) / 2)+"px;");
}

SecondaryCriteria.prototype.remove = function(e, el) {
	var field				= el.getAttribute('field') || false;

	if (field) {
		this.screenerCriteria.removeSecondaryCriteria(field);
	}
}

SecondaryCriteria.prototype.getContent = function() {
	var field 				= this.getField();
	var containerId			= field + 'Container';
	var specificContainer	= Element.get(containerId);

	var criteriaInfo, criteriaControls, preScreenCumulative, 
		preScreenIndividual, removeLink, specificValues, 
		lowValue, lowValueLabel, highValue, highValueLabel, 
		sliderControl, manualControl, 
		backToChart, cumulativeValue, specificValue, 
		inputLow, inputHigh, selectionPanelContainer, 
		buttonControls;
	
	
	if (this.isSliderItem()) {
		
		var minValue_label = this.SCREENER_CRITERIA[field].minvalue_name || false;
		var maxValue_label = this.SCREENER_CRITERIA[field].maxvalue_name || false;
		
		criteriaControls = Element.create("div", {"class":"criteriaControls"}, [
			Element.create("div", {"class":"sliderContainer"}, [
//				(minValue_label ? Element.create("div", {"class":"minValue-label"}, minValue_label) : ""),
				Element.create("div", {"class":"minValue"}),
//				(maxValue_label ? Element.create("div", {"class":"maxValue-label"}, maxValue_label) : ""),
				Element.create("div", {"class":"maxValue"}),
				sliderControl = Element.create("div", {"class":"sliderControl"}, [
					Element.create("div", {"class":"highLowContainer"}, [
						specificValues = Element.create("a", {"href":"javascript:void(0)"}, "Enter specific values"),
						lowValue = Element.create("div", {"class":"lowValue"},[
							Element.create("div",{className:"lowValue-value"}),
							lowValueLabel = Element.create("div",{className:"lowValue-label"})
						]),
						highValue = Element.create("div", {"class":"highValue"},[
							Element.create("div", {className:"highValue-value"}),
							highValueLabel = Element.create("div", {className:"highValue-label"})
						])
					])
				]),
				manualControl = Element.create("div", {"class":"manualControl hide"}, [
					Element.create("div", {"class":"linkContainer"}, [
						backToChart = Element.create("a", {"href":"javascript:void(0)"}, "Go back to the chart")
					]),
					Element.create("div", {"class":"inputContainer"}, [
						Element.create("div", {}, "From"),
						inputLow = Element.create("input", {"operator":"GEQ"})
					]),
					Element.create("div", {"class":"inputDivider"}, "&nbsp;"),
					Element.create("div", {"class":"inputContainer"}, [
						Element.create("div", {}, "To"),
						inputHigh = Element.create("input", {"operator":"LEQ"})
					])
				])
			])
		]);
		
	} else {
		var buttons = this.NON_SLIDER_FIELDS[field];
		var values = this.getValues();
		var settings = values.LIKE || "";
		
		buttonControls = [];
		var isActive = false;
		for (var i = 0, style; i < buttons.length; i++) {
			style = [];
			if (buttons[i].css) { style.push(buttons[i].css); }
			if (settings.match(buttons[i].value)) { style.push("active"); isActive = true; }
			
			buttonControls.push(Element.create("a", {"href":"javascript:void(0)", "criteriaValue":buttons[i].value, "class":style.join(" ")}, buttons[i].display));
		}
		
		criteriaControls = Element.create("div", {"class":"criteriaControls"}, [
			selectionPanelContainer = Element.create("div", {"class":"selectionPanelContainer"}, buttonControls)
		]);
		
		if(isActive) {
			Element.addClass(selectionPanelContainer, "selectionPanelContainer-tampered");
		}
		
		Element.addChild(selectionPanelContainer,
			Element.create("br", {"class":"clear"})
		)
		
		this.getSelectionPanelContainer = function() {
			return selectionPanelContainer;
		}
	}
	
	
	var content = Element.create("div", {"id":field, "class":"criteriaItem hide"}, [
		criteriaInfo = Element.create("div", {"class":"criteriaInfo"}, [
			Element.create("div", {}, this.SCREENER_CRITERIA[field].formatted_name),
			removeLink = Element.create("a", {"href":"javascript:void(0)", field:field }, "remove")
		]),
		criteriaControls,
		Element.create("div", {"class":"criteriaPreScreen"}, 
			Element.create("div",{"class":"criteriaGrad"},[
				preScreenCumulative = Element.create("div", {"class":"preScreen preScreenCumulative"}, [
					Element.create("div", {"id":field+"CumulativeMatches", "class":"preScreenValue"}, "&nbsp;"),
					Element.create("div", {}, "Cumulative Matches")
				]),
				preScreenIndividual = Element.create("div", {"class":"preScreen preScreenIndividual"}, [
					Element.create("div", {"id":field+"Matches", "class":"preScreenValue"}, "&nbsp;"),
					Element.create("div", {}, "Criteria Matches")
				])
			])
		)
	], specificContainer);
	
	this.getContent = function() {
		return content;
	}
	
	this.getCriteriaInfo = function() {
		return criteriaInfo;
	}
	
	this.getCriteriaControls = function() {
		return criteriaControls;
	}
	
	this.getPreScreenCumulative = function() {
		return preScreenCumulative;
	}
	
	this.getPreScreenIndividual = function() {
		return preScreenIndividual;
	}
	
	this.getRemoveLink = function() {
		return removeLink;
	}
	
	this.getSpecificValues = function() {
		return specificValues;
	}
	
	this.getBackToChart = function() {
		return backToChart;
	}
	
	this.getLowValue = function() {
		return lowValue;
	}
	
	this.getHighValue = function() {
		return highValue;
	}
	
	this.getLowValueLabel = function() {
		return lowValueLabel;
	}
	
	this.getHighValueLabel = function() {
		return highValueLabel;
	}
	
	this.getSliderControl = function() {
		return sliderControl;
	}
	
	this.getManualControl = function() {
		return manualControl;
	}
	
	this.getInputLow = function() {
		return inputLow;
	}
	
	this.getInputHigh = function() {
		return inputHigh;
	}
	
	this.getButtonControls = function() {
		return buttonControls;
	}
	
	return this.getContent();
}

SecondaryCriteria.prototype.toggleCriteriaEntry = function(e, el) {
	if (e) { e.cancel(); }
	if (el) { el.blur(); }

	if (Element.hasClass(this.getSliderControl(), "hide")) {
		Element.removeClass(this.getSliderControl(), "hide");
		Element.addClass(this.getManualControl(), "hide");
		
		this.setValues(this.getSliderValues());
	} else {
		Element.addClass(this.getSliderControl(), "hide");
		Element.removeClass(this.getManualControl(), "hide");

		this.setValues(this.getInputValues());
	}

	if (e) { this.screenerCriteria.getPreScreen(); }
}

SecondaryCriteria.prototype.modifySpecificValueTimeout = function(e, el) {
	var operator = el.getAttribute("operator");

	clearTimeout(this['specificValueTimer' + operator]);

	this['specificValueTimer' + operator] = setTimeout(function() {
		var value = el.value;

		this.modifySpecificValue(operator, value); 
	}.Context(this), 500);
}


SecondaryCriteria.prototype.convertSpecificValue = function(value) {
	value = value || false;

	if (!value) {
		return null;
	}

	// Allow the user the option to append a "Magnitude" String to the end of a Number
	var r = /^\s*(-?(?:\d*\.)?\d+)\s*(k|m|mil|million|b|bil|billion)?\s*$/i.exec(value);

	if(!r) return null;

	var n = parseFloat(r[1], 10);

	if(!r[2]) return n;

	switch(r[2].charAt(0).toLowerCase()) {
		case 'k':
			return n * 1000;

		case 'm':
			return n * 1000000;

		case 'b':
			return n * 1000000000;

		default:
			return null;
	}
}


SecondaryCriteria.prototype.modifySpecificValue = function(operator, value) {
	var values = this.getValues();

	values[operator] = this.convertSpecificValue(value);

	this.setValues(values);
	this.screenerCriteria.getPreScreen();
}

SecondaryCriteria.prototype.toggleButtonControl = function(e, el) {
	e.cancel();
	el.blur();
	
	Element.toggleClass(el, "active");
	Element.addClass(this.getSelectionPanelContainer(), "selectionPanelContainer-tampered")
	
	this.setValues(this.getButtonValues());
	this.screenerCriteria.getPreScreen();
}

SecondaryCriteria.prototype.showSpecificValueLink = function() {
	Element.setHTML(this.getSpecificValues(), "Enter specific values");
	if (Element.hasClass(this.getSpecificValues(), "active")) {
		Element.addClass(this.getLowValue(), "hide");
		Element.addClass(this.getHighValue(), "hide");	
	}
}

SecondaryCriteria.prototype.hideSpecificValueLink = function() {
	if (Element.hasClass(this.getSpecificValues(), "active")) {
		Element.setHTML(this.getSpecificValues(), "&nbsp;");
		Element.removeClass(this.getLowValue(), "hide");
		Element.removeClass(this.getHighValue(), "hide");
	}
}

SecondaryCriteria.prototype.getSliderChartFileName = function() { return false; }

SecondaryCriteria.prototype._setSliderValues = function(oParams) {

	oParams = oParams || this.oParams || false;
	if(!oParams) { return false; }
	this.oParams = oParams;
	
	var values = {};
	var coords = [];
	var fileName = oParams.fileName || "";
	
	
	var chartCoords = oParams.coords ? oParams.coords.split(",") : [];
	var chartValues = oParams.values ? oParams.values.split(",") : [];
	
	for (var i = 0, chartReturn, nextChartReturn, val, nextVal; i < chartCoords.length; i++) {
		chartReturn = chartCoords[i];
		nextChartReturn = i < chartCoords.length-1 ? chartCoords[i+1] : chartReturn;
		
		val = Number(chartReturn);
		nextVal = Number(nextChartReturn);
		
		values[val] = Number(chartValues[i]);
		
		for (var j = j || 0; j < this.SLIDER_SIZE; j++) {
			if (j == nextVal) { break; }
			
			coords[j] = Math.abs(j - val) <= Math.abs(j - nextVal) || 0 == j ? val : nextVal;
			if (j == this.SLIDER_SIZE-1) {coords[j+1] = nextVal;}
		}
	}
	
	this.setSliderValues = function() {}
	
	this.getSliderMinValue = function() {
		return values[coords[0]];
	}
	
	this.getSliderMaxValue = function() {
		return values[coords[coords.length-1]];
	}
	
	this.getSliderCoordinates = function() {
		return coords;
	}
	
	this.getSliderValueMap = function() {
		return values;
	}
	
	this.getSliderChartFileName = function() {
		return fileName;
	}
	
	this.drawSlider();

}

SecondaryCriteria.prototype.setSliderValues = function(oParams) {
	this._setSliderValues(oParams);

}

SecondaryCriteria.prototype.drawSlider = function() {
	var values = this.getValues();
	
	var sliderContainer = Element.parseSelector("div.criteriaControls div.sliderContainer", this.getContent(), "first");
	var sliderControl = Element.parseSelector("div.sliderControl", sliderContainer, "first");
	
	Element.setHTML(Element.parseSelector("div.minValue", sliderContainer, "first"), this.formatValue(this.getSliderMinValue()));
	Element.setHTML(Element.parseSelector("div.maxValue", sliderContainer, "first"), this.formatValue(this.getSliderMaxValue()));

	var slider = this.getSlider(sliderControl);

	if (!this.hasSliderLowCoordinate() || !this.hasSliderHighCoordinate()) {
		this.getInputLow().setAttribute("value", undefined !== values.GEQ ? values.GEQ : this.getSliderMinValue());
		this.getInputHigh().setAttribute("value", undefined !== values.LEQ ? values.LEQ : this.getSliderMaxValue());
		
		this.toggleCriteriaEntry();
		
	} else {
		this.setHandleLowPosition(this.getSliderLowCoordinate());
		this.setHandleHighPosition(this.getSliderHighCoordinate());
		
		if (values.GEQ ||values.LEQ) { this.fireHandleEvent(); }
	}
	
	Element.setStyle(slider.sliderBar, "background: url('" + this.getSliderChartFileName() + "') no-repeat 0 0;");
}

SecondaryCriteria.prototype.setHandleLowPosition = function(position) {
	var slider = this.getSlider();
	slider.handles[0].finalDisplayFromPosition(position);
}

SecondaryCriteria.prototype.setHandleHighPosition = function(position) {
	var slider = this.getSlider();
	slider.handles[1].finalDisplayFromPosition(position);
}

SecondaryCriteria.prototype.fireHandleEvent = function(passive) {
	var slider = this.getSlider();
	var handle = slider.handles[0]; // it doesn't matter which handle we use in this case
	
	handle.MyUpdateValue(null, null, passive);
}

SecondaryCriteria.prototype.getSlider = function(parentEl) {
	var slider  = new Slider_Class({
		parentEl: parentEl
		,sliderClass:"sliderControls"
		,orientation: "leftToRight" 
		,handleOverlap: "all"
		,minVal:this.getSliderMinValue()
		,maxVal:this.getSliderMaxValue()
		,sliderSpan: true
		,criteria: this
	});
	var handle1 = new SliderHandle_Class({
		defaultVal:this.getSliderMinValue()
		,tabindex:"1"
		,handleClassName:"slider"
		,coordMap: this.getSliderCoordinates()
		,valueMap: this.getSliderValueMap()
		,criteria: this
	})			
	var handle2 = new SliderHandle_Class({
		defaultVal:this.getSliderMaxValue()
		,tabindex:"2"
		,handleClassName:"slider"
		,coordMap: this.getSliderCoordinates()
		,valueMap: this.getSliderValueMap()
		,criteria: this
	})
	
	var criteria = this.screenerCriteria;
	var sc = this;
	
	var updateValue = function(e, direction, passiveUpdate) {
		
		this.getElSpecificValues = this.getElSpecificValues || function() {
			var elSpecificValues = Element.parseSelector("a", this.parentSliderBar.parentEl, "first");
			
			return (this.getElSpecificValues = function() {
				return elSpecificValues;
			})()
		}
		
		
		this.getElLowValueContainer = this.getElLowValueContainer || function() {
			var elLowVal = Element.parseSelector("div.lowValue", this.parentSliderBar.parentEl, "first");
			
			return (this.getElLowValueContainer = function() {
				return elLowVal;
			})()
		}
		
		this.getElHighValueContainer = this.getElHighValueContainer || function() {
			var elHighValue = Element.parseSelector("div.highValue", this.parentSliderBar.parentEl, "first");
			
			return (this.getElHighValueContainer = function() {
				return elHighValue;
			})()
		}
		
		this.getElLowValue = this.getElLowValue || function() {
			var elLowVal = Element.parseSelector("div.lowValue-value", this.parentSliderBar.parentEl, "first");
			
			return (this.getElLowValue = function() {
				return elLowVal;
			})()
		}
		
		this.getElHighValue = this.getElHighValue || function() {
			var elHighValue = Element.parseSelector("div.highValue-value", this.parentSliderBar.parentEl, "first");
			
			return (this.getElHighValue = function() {
				return elHighValue;
			})()
		}
		
		this.getElLowValueLabel = this.getElLowValueLabel || function() {
			var elLowVal = Element.parseSelector("div.lowValue-label", this.parentSliderBar.parentEl, "first");
			
			return (this.getElLowValueLabel = function() {
				return elLowVal;
			})()
		}
		
		this.getElHighValueLabel = this.getElHighValueLabel || function() {
			var elHighValue = Element.parseSelector("div.highValue-label", this.parentSliderBar.parentEl, "first");
			
			return (this.getElHighValueLabel = function() {
				return elHighValue;
			})()
		}
		
		if(!passiveUpdate) { Element.addClass(this.parentSliderBar.parentEl.parentNode, "active"); }
		

		var tampered = false;
		if(!passiveUpdate || this.getElLowValue().innerHTML != "") {
			var lowVal = this.parentSliderBar.handles[0].getValue();
			var rawLowVal = this.parentSliderBar.handles[0].getValue(true);
			Element.setHTML(this.getElLowValue(), sc.formatValue(lowVal));
			for(var i in sc.dynamic_labels) {
				if(Number(i) < Number(rawLowVal)) {
					Element.setHTML(this.getElLowValueLabel(), sc.dynamic_labels[i]);
					break;
				}
			}
			tampered = true;
		}
		
		if(!passiveUpdate || this.getElHighValue().innerHTML != "") {
			var highVal = this.parentSliderBar.handles[1].getValue();
			var rawHighVal = this.parentSliderBar.handles[1].getValue(true);
			Element.setHTML(this.getElHighValue(), sc.formatValue(highVal));
			for(var i in sc.dynamic_labels) {
				if(Number(i) >= Number(rawHighVal)) {
					Element.setHTML(this.getElHighValueLabel(), sc.dynamic_labels[i]);
					break;
				}
			}
			tampered = true;
		}		
		
		if(tampered) {
			Element.setHTML(this.getElSpecificValues(), "&nbsp;");
		}
		
		if(!passiveUpdate) { 
			Element.addClass(this.getElSpecificValues(), "active"); 
			sc.setSliderValueLow(this.parentSliderBar.handles[0].getValue());
			sc.setSliderValueHigh(this.parentSliderBar.handles[1].getValue());
		}
		
		
		if(!passiveUpdate) { sc.setValues(sc.getSliderValues()); }
		
		if(!passiveUpdate) {
			var lowWidth = Element.getSize(this.getElLowValueContainer()).width;
			
			this.handleEdgePosition1 = this.parentSliderBar.handles[0].currentPosition - lowWidth;
			this.handleEdgePosition2 = this.parentSliderBar.handles[1].currentPosition - 0;
			this.getElLowValueContainer().style.left = this.handleEdgePosition1 + "px";
			this.getElHighValueContainer().style.left = this.handleEdgePosition2 + "px";
		}
		
		if (e) {
			clearTimeout(this.timer);
			this.timer = setTimeout(function() { criteria.getPreScreen(); }, 250);
		}
	}

	handle1.MyUpdateValue = updateValue;
	handle2.MyUpdateValue = updateValue;
	
	slider.addHandle(handle1, handle2);

	this.getSlider = function() {
		return slider;
	}
	
	return this.getSlider();
}

SecondaryCriteria.prototype.getSliderValueLow = function() { return null; }
SecondaryCriteria.prototype.setSliderValueLow = function(val) {
	var valueLow;
	
	this.getSliderValueLow = function() {
		return valueLow;
	}
	
	this.setSliderValueLow = function(val) {
		if (this.getSliderMinValue() != val) {
			valueLow = val;
		} else {
			valueLow = null;
		}
	}
	
	return this.setSliderValueLow(val);
}

SecondaryCriteria.prototype.getSliderValueHigh = function() { return null; }
SecondaryCriteria.prototype.setSliderValueHigh = function(val) {
	var valueHigh = val;
	
	this.getSliderValueHigh = function() {
		return valueHigh;
	}
	
	this.setSliderValueHigh = function(val) {
		if (this.getSliderMaxValue() != val) {
			valueHigh = val;
		} else {
			valueHigh = null;
		}
	}
	
	return this.setSliderValueHigh(val);
}

SecondaryCriteria.prototype.getSliderValues = function() {
	var valLow = this.getSliderValueLow();
	var valHigh = this.getSliderValueHigh();
	
	var values = {}
	if (valLow) { values.GEQ = valLow; }
	if (valHigh) { values.LEQ = valHigh; }
	
	return values;
}

SecondaryCriteria.prototype.getInputValueLow = function() {
	return this.getInputLow().value || null;
}

SecondaryCriteria.prototype.getInputValueHigh = function() {
	return this.getInputHigh().value || null;
}

SecondaryCriteria.prototype.getInputValues = function() {
	var valLow = this.getInputValueLow();
	var valHigh = this.getInputValueHigh();

	var values = {}
	if (valLow) { values.GEQ = this.convertSpecificValue(valLow); }
	if (valHigh) { values.LEQ = this.convertSpecificValue(valHigh); }

	return values;
}

SecondaryCriteria.prototype.getButtonValues = function() {
	var buttonControls = this.getButtonControls();
	
	for (var i = 0, settings = []; i < buttonControls.length; i++) {
		if (Element.hasClass(buttonControls[i], "active")) { settings.push(buttonControls[i].getAttribute("criteriaValue")); };
	}
	
	var values = {};
	if (settings.length) { values.LIKE = settings.join(","); }
	
	return values;
}

SecondaryCriteria.prototype.checkSliderValues = function() {
	var sliderCheck = {};
	
	var values = this.getValues();
	var sliderValues = this.getSliderValueMap();
	
	sliderCheck.hasLowValue = values.GEQ ? false : true;
	sliderCheck.hasHighValue = values.LEQ ? false : true;
	sliderCheck.coordLowValue = values.GEQ ? null : 0;
	sliderCheck.coordHighValue = values.LEQ ? null : this.SLIDER_SIZE;
	
	for (var i in sliderValues) {
		if (values.GEQ == sliderValues[i]) {
			sliderCheck.hasLowValue = true;
			sliderCheck.coordLowValue = i;
		} else if (values.LEQ == sliderValues[i]) {
			sliderCheck.hasHighValue = true;
			sliderCheck.coordHighValue = i;
		}
	}
	
	this.checkSliderValues = function() {
		return sliderCheck;
	}
	
	return this.checkSliderValues();
}

SecondaryCriteria.prototype.hasSliderLowCoordinate = function() {
	return this.checkSliderValues().hasLowValue;
}

SecondaryCriteria.prototype.hasSliderHighCoordinate = function() {
	return this.checkSliderValues().hasHighValue;
}

SecondaryCriteria.prototype.getSliderLowCoordinate = function() {
	return this.checkSliderValues().coordLowValue;
}

SecondaryCriteria.prototype.getSliderHighCoordinate = function() {
	return this.checkSliderValues().coordHighValue;
}

SecondaryCriteria.prototype.exportCriteria = function() {
	var criteria = {field: this.getField()};
	var values = this.getValues();
	
	var vals = [];
	for (var i in values) {
		vals.push([i, ":", values[i]].join(""));
	}
	
	if (vals.length) {
		criteria.values = [vals.join("|")];
	}
	
	if (!this.getSliderChartFileName() && !this.NON_SLIDER_FIELDS[this.getField()]) {
		criteria.getChart = true;
	}

	return criteria;
}

SecondaryCriteria.prototype.formatValue = function(value) {
	
	
	var rawValue = value;
	var magValue = Math.abs(value);
	var numDecimals = 4;
	var magnitude = "";
	
	if (magValue >= 1000000000000) {
		magnitude = "T";
		value /= 1000000000000;
	} else if (magValue >= 1000000000) {
		magnitude = "B";
		value /= 1000000000;
	} else if (magValue >= 1000000) {
		magnitude = "M";
		value /= 1000000;
	} else if (magValue >= 1000) {
		magnitude = "K";
		value /= 1000;
	}
	
	if (magValue >= 0.1) {
		numDecimals = 1;
	} else if (magValue >= 0.01) {
		numDecimals = 2;
	} else if (magValue <= 0.0001 && rawValue > 0) {
		value = 0;
		numDecimals = 0;
	} else {
		numDecimals = 2;
	}
	
	
	var newval = "";
	try {
		newval = value.toFixed(numDecimals) + magnitude
	} catch(e) {
		newval = 0;
	}
	return newval;
}

SecondaryCriteria.prototype.getEventManager = function() {
	var em = new EventManager();
	this.getEventManager = function() {
		return em;
	};
	return this.getEventManager();
};